抽象:

Shader.h:

#pragma once

#include

namespace YOTO {

class Shader {

public:

virtual~Shader()=default;

virtual void Bind()const=0;

virtual void UnBind()const=0;

static Shader* Create(const std::string& vertexSrc, const std::string& fragmentSrc);

}

;

}

Shader.cpp:

#include "ytpch.h"

#include "Shader.h"

#include"Renderer.h"

#include "Platform/OpenGL/OpenGLShader.h"

namespace YOTO {

Shader* Shader::Create(const std::string& vertexSrc, const std::string& fragmentSrc)

{

switch (Renderer::GetAPI())

{

case RendererAPI::API::None:

YT_CORE_ASSERT(false, "Buffer:API为None不支持");

return nullptr;

case RendererAPI::API::OpenGL:

return new OpenGLShader(vertexSrc, fragmentSrc);

}

YT_CORE_ASSERT(false, "Buffer:未知API");

return nullptr;

}

}

实现:

新建OpenGLShader类:

OpenGLShader.h

#pragma once

#include

#include "YOTO/Renderer/Shader.h"

#include

namespace YOTO {

class OpenGLShader:public Shader {

public:

OpenGLShader(const std::string& vertexSrc, const std::string& fragmentSrc);

~OpenGLShader();

void Bind()const override;

void UnBind()const override;

void UploadUniformMat4(const std::string& name, const glm::mat4& matrix);

void UploadUniformMat3(const std::string& name, const glm::mat3& matrix);

void UploadUniformFloat4(const std::string& name, const glm::vec4& values);

void UploadUniformFloat3(const std::string& name, const glm::vec3& values);

void UploadUniformFloat2(const std::string& name, const glm::vec2& values);

void UploadUniformFloat(const std::string& name, float values);

void UploadUniformInt(const std::string& name, int values);

private:

uint32_t m_RendererID;

}

;

}

 OpenGLShader.cpp

#include "ytpch.h"

#include "OpenGLShader.h"

#include

#include

#include

namespace YOTO {

OpenGLShader::OpenGLShader(const std::string& vertexSrc, const std::string& fragmentSrc)

{

// 1.1.创建顶点着色器对象

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

// Send the vertex shader source code to GL

// Note that std::string's .c_str is NULL character terminated.

// 1.2.附加顶点着色器源码到顶点着色器对象中

const GLchar* source = vertexSrc.c_str();

glShaderSource(vertexShader, 1, &source, 0);

// 1.3.编译顶点着色器对象

glCompileShader(vertexShader);

// 1.4.检查是否编译成功

GLint isCompiled = 0;

glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);

if (isCompiled == GL_FALSE) {

// 1.4.2编译失败可以打印报错信息

GLint maxLength = 0;

glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);

// The maxLength includes the NULL character

std::vector infoLog(maxLength);

glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);

// We don't need the shader anymore.

glDeleteShader(vertexShader);

YT_CORE_ERROR("{0}", infoLog.data());

YT_CORE_ASSERT(false, "Vertex shader compilation failure!");

return;

}

// 片段着色器一样

// 2.1.创建片段着色器对象

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

// Send the fragment shader source code to GL

// Note that std::string's .c_str is NULL character terminated.

// 2.2.附加片段着色器源码到片段着色器对象中

source = fragmentSrc.c_str();

glShaderSource(fragmentShader, 1, &source, 0);

// 2.3.编译片段着色器对象

glCompileShader(fragmentShader);

// 2.4.检查是否编译成功

glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);

if (isCompiled == GL_FALSE) {

// 2.4.2编译失败可以打印报错信息

GLint maxLength = 0;

glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);

// The maxLength includes the NULL character

std::vector infoLog(maxLength);

glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);

// We don't need the shader anymore.

glDeleteShader(fragmentShader);

// Either of them. Don't leak shaders.

glDeleteShader(vertexShader);

YT_CORE_ERROR("{0}", infoLog.data());

YT_CORE_ASSERT(false, "Fragment shader compilation failure!");

return;

}

// Vertex and fragment shaders are successfully compiled.

// Now time to link them together into a program.

// Get a program object.

// 3.1创建着色器程序对象

m_RendererID = glCreateProgram();

GLuint program = m_RendererID;

// 3.2附加着色器对象给着色器程序对象

glAttachShader(program, vertexShader);

glAttachShader(program, fragmentShader);

// 3.3链接着色器程序对象

glLinkProgram(program);

// 3.4可以检查链接是否成功

// Note the different functions here: glGetProgram* instead of glGetShader*.

GLint isLinked = 0;

glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);

if (isLinked == GL_FALSE) {

GLint maxLength = 0;

glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

// The maxLength includes the NULL character

std::vector infoLog(maxLength);

glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);

// We don't need the program anymore.

glDeleteProgram(program);

// Don't leak shaders either.

glDeleteShader(vertexShader);

glDeleteShader(fragmentShader);

YT_CORE_ERROR("{0}", infoLog.data());

YT_CORE_ASSERT(false, "Shader link failure!");

return;

}

// 4.删除着色器对象

// Always detach shaders after a successful link.

glDetachShader(program, vertexShader);

glDetachShader(program, fragmentShader);

}

OpenGLShader::~OpenGLShader()

{

glDeleteProgram(m_RendererID);

}

void OpenGLShader::Bind() const

{

glUseProgram(m_RendererID);

}

void OpenGLShader::UnBind() const

{

glUseProgram(0);

}

void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniformMatrix4fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix));

}

void OpenGLShader::UploadUniformMat3(const std::string& name, const glm::mat3& matrix)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniformMatrix3fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix));

}

void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& values)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniform4f(loacation, values.x, values.y, values.z, values.w);

}

void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& values)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniform3f(loacation, values.x, values.y, values.z);

}

void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& values)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniform2f(loacation, values.x, values.y);

}

void OpenGLShader::UploadUniformFloat(const std::string& name, float values)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniform1f(loacation, values);

}

void OpenGLShader::UploadUniformInt(const std::string& name, int values)

{

GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());

glUniform1i(loacation, values);

}

}

测试:

#include

#include "imgui/imgui.h"

#include

#include

#include

#include

class ExampleLayer:public YOTO::Layer

{

public:

ExampleLayer()

:Layer("Example"), m_Camera(-2.0f, 2.0f, -2.0f, 2.0f), m_CameraPosition(0){

uint32_t indices[3] = { 0,1,2 };

float vertices[3 * 7] = {

-0.5f,-0.5f,0.0f, 0.8f,0.2f,0.8f,1.0f,

0.5f,-0.5f,0.0f, 0.2f,0.3f,0.8f,1.0f,

0.0f,0.5f,0.0f, 0.8f,0.8f,0.2f,1.0f,

};

m_VertexArray.reset(YOTO::VertexArray::Create());

std::shared_ptr m_VertexBuffer;

m_VertexBuffer.reset(YOTO::VertexBuffer::Create(vertices, sizeof(vertices)));

{

YOTO::BufferLayout setlayout = {

{YOTO::ShaderDataType::Float3,"a_Position"},

{YOTO::ShaderDataType::Float4,"a_Color"}

};

m_VertexBuffer->SetLayout(setlayout);

}

m_VertexArray->AddVertexBuffer(m_VertexBuffer);

std::shared_ptrm_IndexBuffer;

m_IndexBuffer.reset(YOTO::IndexBuffer::Create(indices, sizeof(indices) / sizeof(uint32_t)));

m_VertexArray->AddIndexBuffer(m_IndexBuffer);

std::string vertexSource = R"(

#version 330 core

layout(location = 0) in vec3 a_Position;

layout(location = 1) in vec4 a_Color;

uniform mat4 u_ViewProjection;

uniform mat4 u_Transform;

out vec3 v_Position;

out vec4 v_Color;

void main(){

v_Position=a_Position;

v_Color=a_Color;

gl_Position =u_ViewProjection *u_Transform* vec4( a_Position,1.0);

}

)";

//绘制颜色

std::string fragmentSource = R"(

#version 330 core

layout(location = 0) out vec4 color;

in vec3 v_Position;

in vec4 v_Color;

void main(){

color=vec4(v_Color);

}

)";

m_Shader.reset(YOTO::Shader::Create(vertexSource, fragmentSource));

///测试/

m_SquareVA.reset(YOTO::VertexArray::Create());

float squareVertices[3 * 4] = {

-0.5f,-0.5f,0.0f,

0.5f,-0.5f,0.0f,

0.5f,0.5f,0.0f,

-0.5f,0.5f,0.0f

};

std::shared_ptr squareVB;

squareVB.reset(YOTO::VertexBuffer::Create(squareVertices, sizeof(squareVertices)));

squareVB->SetLayout({

{YOTO::ShaderDataType::Float3,"a_Position"}

});

m_SquareVA->AddVertexBuffer(squareVB);

uint32_t squareIndices[6] = { 0,1,2,2,3,0 };

std::shared_ptr squareIB;

squareIB.reset((YOTO::IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t))));

m_SquareVA->AddIndexBuffer(squareIB);

//测试:

std::string BlueShaderVertexSource = R"(

#version 330 core

layout(location = 0) in vec3 a_Position;

uniform mat4 u_ViewProjection;

uniform mat4 u_Transform;

out vec3 v_Position;

void main(){

v_Position=a_Position;

gl_Position =u_ViewProjection*u_Transform*vec4( a_Position,1.0);

}

)";

//绘制颜色

std::string BlueShaderFragmentSource = R"(

#version 330 core

layout(location = 0) out vec4 color;

in vec3 v_Position;

uniform vec3 u_Color;

void main(){

color=vec4(u_Color,1.0);

}

)";

m_BlueShader.reset(YOTO::Shader::Create(BlueShaderVertexSource, BlueShaderFragmentSource));

}

void OnImGuiRender() override {

ImGui::Begin("设置");

ImGui::ColorEdit3("正方形颜色", glm::value_ptr(m_SquareColor));

ImGui::End();

}

void OnUpdate(YOTO::Timestep ts)override {

YT_CLIENT_TRACE("delta time {0}s ({1}ms)", ts.GetSeconds(), ts.GetMilliseconds());

if (YOTO::Input::IsKeyPressed(YT_KEY_LEFT)) {

m_CameraPosition.x -= m_CameraMoveSpeed* ts;

}

else if (YOTO::Input::IsKeyPressed(YT_KEY_RIGHT)) {

m_CameraPosition.x += m_CameraMoveSpeed * ts;

}

if (YOTO::Input::IsKeyPressed(YT_KEY_DOWN)) {

m_CameraPosition.y -= m_CameraMoveSpeed * ts;

}

else if (YOTO::Input::IsKeyPressed(YT_KEY_UP)) {

m_CameraPosition.y += m_CameraMoveSpeed * ts;

}

if (YOTO::Input::IsKeyPressed(YT_KEY_A)) {

m_CameraRotation += m_CameraRotationSpeed * ts;

}else if (YOTO::Input::IsKeyPressed(YT_KEY_D)) {

m_CameraRotation -= m_CameraRotationSpeed * ts;

}

YOTO::RenderCommand::SetClearColor({ 0.2f, 0.2f, 0.2f, 1.0f });

YOTO::RenderCommand::Clear();

m_Camera.SetPosition(m_CameraPosition);

m_Camera.SetRotation(m_CameraRotation);

YOTO::Renderer::BeginScene(m_Camera);

{

static glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f));

glm::vec4 redColor(0.8f, 0.3f, 0.3f, 1.0f);

glm::vec4 blueColor(0.2f, 0.3f, 0.8f, 1.0f);

/* YOTO::MaterialRef material = new YOTO::MaterialRef(m_FlatColorShader);

YOTO::MaterialInstaceRef mi = new YOTO::MaterialInstaceRef(material);

mi.setValue("u_Color",redColor);

mi.setTexture("u_AlbedoMap", texture);

squreMesh->SetMaterial(mi);*/

std::dynamic_pointer_cast(m_BlueShader)->Bind();

std::dynamic_pointer_cast(m_BlueShader)->UploadUniformFloat3("u_Color",m_SquareColor);

for (int y = 0; y < 20; y++) {

for (int x = 0; x <20; x++)

{

glm::vec3 pos(x * 0.11f,y* 0.11f, 0.0);

glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos) * scale;

/*if (x % 2 == 0) {

m_BlueShader->UploadUniformFloat4("u_Color", redColor);

}

else {

m_BlueShader->UploadUniformFloat4("u_Color", blueColor);

}*/

YOTO::Renderer::Submit(m_BlueShader, m_SquareVA, transform);

}

}

YOTO::Renderer::Submit(m_Shader, m_VertexArray);

YOTO::Renderer::EndScene();

}

}

void OnEvent(YOTO::Event& event)override {

/*if (event.GetEventType() == YOTO::EventType::KeyPressed) {

YOTO:: KeyPressedEvent& e = (YOTO::KeyPressedEvent&)event;

YT_CLIENT_TRACE("ExampleLayer:{0}",(char)e.GetKeyCode());

if (e.GetKeyCode()==YT_KEY_TAB) {

YT_CLIENT_INFO("ExampleLayerOnEvent:TAB按下了");

}}*/

//YT_CLIENT_TRACE("SandBoxApp:测试event{0}", event);

}

private:

std::shared_ptr m_Shader;

std::shared_ptr m_VertexArray;

std::shared_ptr m_BlueShader;

std::shared_ptr m_SquareVA;

YOTO::OrthographicCamera m_Camera;

glm::vec3 m_CameraPosition;

float m_CameraMoveSpeed = 5.0f;

float m_CameraRotation = 0;

float m_CameraRotationSpeed = 180.0f;

glm::vec3 m_SquareColor = { 0.2f,0.3f,0.7f };

};

class Sandbox:public YOTO::Application

{

public:

Sandbox(){

PushLayer(new ExampleLayer());

//PushLayer(new YOTO::ImGuiLayer());

}

~Sandbox() {

}

private:

};

YOTO::Application* YOTO::CreateApplication() {

printf("helloworld");

return new Sandbox();

}

 cool!

小修改:

Core.h:

#pragma once

#include

//用于dll的宏

#ifdef YT_PLATFORM_WINDOWS

#if YT_DYNAMIC_LINK

#ifdef YT_BUILD_DLL

#define YOTO_API __declspec(dllexport)

#else

#define YOTO_API __declspec(dllimport)

#endif // DEBUG

#else

#define YOTO_API

#endif

#else

#error YOTO_ONLY_SUPPORT_WINDOWS

#endif // YOTO_PLATFORM_WINDOWS

#ifdef YT_DEBUG

#define YT_ENABLE_ASSERTS

#endif

#ifdef YT_ENABLE_ASSERTS

#define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}

#define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}

#else

#define YT_CLIENT_ASSERT(x,...)

#define YT_CORE_ASSERT(x,...)

#endif // YT_ENABLE_ASSERTS

#define BIT(x)(1<

//绑定事件定义

#define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

namespace YOTO {

template

using Scope = std::unique_ptr;

template

using Ref = std::shared_ptr;

}

之后把所有share_ptr的地方改成Ref就好了。

参考阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。