Shader abstraction

This commit is contained in:
Tom
2021-06-10 17:11:54 +02:00
parent 3b9db30488
commit 890c36bfc1
18 changed files with 174 additions and 106 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,3 @@
Renderer.cpp
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
glew32s.lib(glew.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'glew32s.lib(glew.obj)' or at 'C:\dev\Glfw_Practice\c++\Window_practice\Debug\vc120.pdb'; linking object as if no debug info
Main.cpp
C:\dev\Glfw_Practice\c++\Window_practice\Window_practice\src\VertexBufferLayout.h(5,10): warning C4067: unexpected tokens following preprocessor directive - expected a newline
Window_practice.vcxproj -> C:\dev\Glfw_Practice\c++\Window_practice\Debug\Window_practice.exe

Binary file not shown.

Binary file not shown.

View File

@@ -148,6 +148,7 @@
<ClCompile Include="src\IndexBuffer.cpp" />
<ClCompile Include="src\Main.cpp" />
<ClCompile Include="src\Renderer.cpp" />
<ClCompile Include="src\Shader.cpp" />
<ClCompile Include="src\VertexArray.cpp" />
<ClCompile Include="src\VertexBuffer.cpp" />
</ItemGroup>
@@ -155,6 +156,7 @@
<ClInclude Include="src\IndexBuffer.h" />
<ClInclude Include="src\Main.h" />
<ClInclude Include="src\Renderer.h" />
<ClInclude Include="src\Shader.h" />
<ClInclude Include="src\VertexArray.h" />
<ClInclude Include="src\VertexBuffer.h" />
<ClInclude Include="src\VertexBufferLayout.h" />

View File

@@ -30,6 +30,9 @@
<ClCompile Include="src\VertexArray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Shader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Main.h">
@@ -50,6 +53,9 @@
<ClInclude Include="src\VertexBufferLayout.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Shader.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="res\shaders\Basic.shader" />

View File

@@ -2,93 +2,12 @@
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Renderer.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "VertexArray.h"
struct ShaderProgramSource {
std::string VertexSource;
std::string FragmentSource;
};
//For reading in the shader from file
static ShaderProgramSource ParseShader(const std::string& filepath) {
std::ifstream stream(filepath);
enum class ShaderType {
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2]; //one is the vertex other is the fragment shader
ShaderType type = ShaderType::NONE;
while (getline(stream, line)) {
if (line.find("#shader") != std::string::npos) {
if (line.find("vertex") != std::string::npos) {
//set mode to vertex
type = ShaderType::VERTEX;
}
else if (line.find("fragment") != std::string::npos) {
//set mode to fragment
type = ShaderType::FRAGMENT;
}
}
else {
ss[(int)type] << line << "\n";
}
}
return { ss[0].str(), ss[1].str() };
}
//Shader compiler
static unsigned int CompileShader(unsigned int type, const std::string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
//Error handling
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)_malloca(length * sizeof(char)); //_malloca is more secure than alloca
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " <<
(type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
#include "Shader.h"
int main(void){
// GLFW init
@@ -147,23 +66,15 @@ int main(void){
va.AddBuffer(vb, layout);
IndexBuffer ib(indecies, 6);
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");
//Creating the shader
unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);
glUseProgram(shader);
//Shader Uniform
//need to bound a shader before this
GLCall(int location = glGetUniformLocation(shader, "u_Color")); //finding u_Color location
ASSERT(location != -1);
GLCall(glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f));
Shader shader("res/shaders/Basic.shader");
shader.Bind();
shader.SetUniform4f("u_Color", 0.8f, 0.3f, 0.8f, 1.0f);
//unbinding the buffers
GLCall(glBindVertexArray(0));
GLCall(glUseProgram(0));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
va.Unbind();
vb.Unbind();
ib.Unbind();
shader.Unbind();
//for animation
float r = 0.0f;
@@ -174,8 +85,8 @@ int main(void){
/* Render here */
GLCall(glClear(GL_COLOR_BUFFER_BIT));
GLCall(glUseProgram(shader));
GLCall(glUniform4f(location, r, 0.3f, 0.8f, 1.0f));
shader.Bind();
shader.SetUniform4f("u_Color", r, 0.3f, 0.8f, 1.0f);
va.Bind();
ib.Bind();
@@ -195,9 +106,8 @@ int main(void){
/* Poll for and process events */
GLCall(glfwPollEvents());
}
GLCall(glDeleteProgram(shader));
}
glfwTerminate();
return 0;
}

View File

@@ -0,0 +1,122 @@
#include "Shader.h"
#include "Renderer.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
Shader::Shader(const std::string& filepath)
:m_FilePath(filepath), m_RendererID(0)
{
ShaderProgramSource source = ParseShader(filepath);
m_RendererID = CreateShader(source.VertexSource, source.FragmentSource);
}
Shader::~Shader()
{
GLCall(glDeleteProgram(m_RendererID));
}
unsigned int Shader::CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
unsigned int Shader::CompileShader(unsigned int type, const std::string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
//Error handling
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)_malloca(length * sizeof(char)); //_malloca is more secure than alloca
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " <<
(type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
//For reading in the shader from file
ShaderProgramSource Shader::ParseShader(const std::string& filepath) {
std::ifstream stream(filepath);
enum class ShaderType {
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2]; //one is the vertex other is the fragment shader
ShaderType type = ShaderType::NONE;
while (getline(stream, line)) {
if (line.find("#shader") != std::string::npos) {
if (line.find("vertex") != std::string::npos) {
//set mode to vertex
type = ShaderType::VERTEX;
}
else if (line.find("fragment") != std::string::npos) {
//set mode to fragment
type = ShaderType::FRAGMENT;
}
}
else {
ss[(int)type] << line << '\n';
}
}
return { ss[0].str(), ss[1].str() };
}
void Shader::Bind() const
{
GLCall(glUseProgram(m_RendererID));
}
void Shader::Unbind() const
{
GLCall(glUseProgram(0));
}
void Shader::SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3)
{
GLCall(glUniform4f(GetUniformLocation(name), v0, v1, v2, v3));
}
unsigned int Shader::GetUniformLocation(const std::string& name)
{
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
return m_UniformLocationCache[name];
GLCall(unsigned int location = glGetUniformLocation(m_RendererID, name.c_str()));
if (location == -1)
std::cout << "Warning: uniform '" << name << "' does not exist!" << std::endl;
m_UniformLocationCache[name] = location;
return location;
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <unordered_map>
struct ShaderProgramSource {
std::string VertexSource;
std::string FragmentSource;
};
class Shader {
private:
std::string m_FilePath;
unsigned int m_RendererID;
std::unordered_map<std::string, unsigned int> m_UniformLocationCache;
public:
Shader(const std::string& filepath);
~Shader();
void Bind() const;
void Unbind() const;
//Set uniform
void SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3);
private:
ShaderProgramSource ParseShader(const std::string& filepath);
unsigned int CompileShader(unsigned int type, const std::string& source);
unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader);
unsigned int GetUniformLocation(const std::string& name);
};