Browse Source

add simple mesh, render object, and shader types

testing
cinnaboot 6 years ago
parent
commit
b7e6f5af21
  1. 9
      examples/Makefile
  2. 8
      examples/assimp_loading/main.cpp
  3. 54
      examples/simple_mesh/main.cpp
  4. 17
      include/entity.h
  5. 2
      include/lights.h
  6. 9
      include/mesh.h
  7. 21
      include/render_object.h
  8. 11
      include/renderer.h
  9. 36
      include/shader_program.h
  10. 32
      src/default_shaders.cpp
  11. 67
      src/entity.cpp
  12. 2
      src/lights.cpp
  13. 10
      src/mesh.cpp
  14. 61
      src/render_object.cpp
  15. 142
      src/renderer.cpp
  16. 134
      src/shader_program.cpp

9
examples/Makefile

@ -7,7 +7,10 @@ LIB = ../build/libTangerine.a
BINDIR = bin
all: mkdirs $(OBJDIR)/hello_world.o $(OBJDIR)/assimp_loading.o
all: mkdirs \
$(OBJDIR)/hello_world.o \
$(OBJDIR)/assimp_loading.o \
$(OBJDIR)/simple_mesh.o
.PHONY: all
-include $(OBJDIR)/*.d
@ -24,6 +27,10 @@ $(OBJDIR)/assimp_loading.o: $(LIB)
$(CXX) $(CXXFLAGS) -c -MMD assimp_loading/main.cpp -o $@
$(CXX) -o $(BINDIR)/assimp_loading $(LDFLAGS) $@ $(LIB)
$(OBJDIR)/simple_mesh.o: $(LIB)
$(CXX) $(CXXFLAGS) -c -MMD simple_mesh/main.cpp -o $@
$(CXX) -o $(BINDIR)/simple_mesh $(LDFLAGS) $@ $(LIB)
clean:
rm -rf $(OBJDIR)/* bin/*
.PHONY: clean

8
examples/assimp_loading/main.cpp

@ -4,8 +4,9 @@
#include "camera.h"
#include "dumbLog.h"
#include "renderer.h"
#include "entity.h"
#include "renderer.h"
#include "shader_program.h"
void
@ -27,7 +28,8 @@ main()
}
// TODO: this needs to be more convenient
rs->render_groups = renAllocateGroup(1, *rs->default_shader);
shader_wrapper sw = { DEFAULT_SHADER, rs->default_shader, nullptr };
rs->render_groups = renAllocateGroup(1, sw);
rs->render_group_count = 1;
entity& spaceship = rs->render_groups->entities[0];
@ -48,7 +50,7 @@ main()
// NOTE: testing assimp animation info
logDebugAnimationInfo("../data/spaceship.glb");
if (entInit(spaceship, "../data/spaceship.glb")) {
if (entInitModel(spaceship, "../data/spaceship.glb")) {
// TODO: this should be handled in entInit
entSetWorldPosition(spaceship, glm::vec3(0, 0, 0));
entScale(spaceship, glm::vec3(20, 20, 20));

54
examples/simple_mesh/main.cpp

@ -0,0 +1,54 @@
#include <glm/glm.hpp>
#include "dumbLog.h"
#include "mesh.h"
#include "renderer.h"
int
main()
{
render_state* rs = renInit("simple mesh");
if (rs == nullptr) {
LOG(Error) << "Error Initialzing renderer\n";
return 1;
}
// TODO: this needs to be more convenient
shader_wrapper sw = { SIMPLE_SHADER, nullptr, rs->simple_shader };
rs->render_groups = renAllocateGroup(1, sw);
rs->render_group_count = 1;
entity& e = rs->render_groups->entities[0];
// manually construct a simple mesh
simple_mesh mesh = {0};
mesh.num_vertices = 4;
mesh.vertices = UTIL_ALLOC(mesh.num_vertices, glm::vec3);
mesh.vertices[0] = glm::vec3(-200, 0, 200);
mesh.vertices[1] = glm::vec3(-200, 0, -200);
mesh.vertices[2] = glm::vec3(200, 0, -200);
mesh.vertices[3] = glm::vec3(200, 0, 200);
mesh.vert_colors = UTIL_ALLOC(mesh.num_vertices, glm::vec3);
mesh.vert_colors[0] = glm::vec3(255, 0, 0);
mesh.vert_colors[1] = glm::vec3(255, 0, 0);
mesh.vert_colors[2] = glm::vec3(255, 0, 0);
mesh.vert_colors[3] = glm::vec3(255, 0, 0);
//initialize entity with new mesh
entInitSimpleMesh(e, mesh, GL_LINE_LOOP);
utilSafeFree(mesh.vertices);
utilSafeFree(mesh.vert_colors);
cameraInitPerspective(
rs->cam,
glm::vec3(0, -500, 0),
glm::vec3(0, 0, 0),
glm::vec3(0,0,1)
);
renDoRenderLoop(rs);
renShutdown(rs);
return 0;
}

17
include/entity.h

@ -7,19 +7,32 @@
#include "render_object.h"
enum mesh_group_type
{
DEFAULT_MESHES = 0,
SIMPLE_MESH = 1
};
struct entity
{
glm::mat4 world_transform;
mesh_group_type mesh_type;
simple_mesh mesh;
simple_render_object simple_ro;
GLenum draw_mode;
// TODO: should be a pointer into a global array of mesh_info(s) or
// mesh_groups stored on the render_state object
mesh_group meshes;
render_object* render_objs;
uint ro_count;
};
bool entInit(entity& e, const char* model_path);
bool entInitModel(entity& e, const char* model_path);
bool entInitSimpleMesh(entity& e, simple_mesh& mesh, GLenum draw_mode);
void entFree(entity& e);

2
include/lights.h

@ -30,5 +30,5 @@ void lightsOut(light_group* lights);
bool
lightsAdd(light_group* lights, glm::vec3 pos, glm::vec3 color, float intensity);
void lightsUpdate(light_group* lights, shader_program* shader);
void lightsUpdate(light_group* lights, default_shader_program* shader);

9
include/mesh.h

@ -34,6 +34,13 @@ struct mesh_group
uint num_meshes;
};
struct simple_mesh
{
glm::vec3* vertices;
glm::vec3* vert_colors;
uint num_vertices;
};
bool meInitAssimp();
@ -43,5 +50,7 @@ bool meLoadFromFile(mesh_group& mesh_group, const char* filepath);
void meFreeMeshGroup(mesh_group& mesh_group);
void meFreeSimpleMesh(simple_mesh& mesh);
void meShutdownAssimp();

21
include/render_object.h

@ -19,14 +19,31 @@ struct render_object
GLuint normal_buffer_id;
GLuint uv_buffer_id;
GLuint index_buffer_id;
GLuint index_buffer_count;
uint index_buffer_count;
};
struct simple_render_object
{
GLuint vertex_buffer_id;
GLuint vertex_color_buffer_id;
uint vertex_count;
};
bool roInit(mesh_info* mi_in, render_object& ro_out);
bool roInitSimpleMesh(simple_mesh& mesh_in, simple_render_object& ro_out);
void roFree(render_object& ro);
void roFreeSimple(simple_render_object& ro);
void roDraw(render_object& ro,
camera& cam,
shader_program& shader,
default_shader_program& shader,
light_group* lights);
void roDrawSimple(simple_render_object& ro,
camera& cam,
simple_shader_program& shader,
GLenum draw_mode);

11
include/renderer.h

@ -26,10 +26,11 @@ struct SDL_Handles
// NOTE: array of entities rendered with the same shader program
struct render_group
{
// TODO: also needs to be resizable
entity* entities;
uint entity_count;
shader_program shader;
shader_wrapper shader;
};
struct render_state
@ -44,7 +45,9 @@ struct render_state
render_group* render_groups;
uint render_group_count;
shader_program* default_shader;
default_shader_program* default_shader;
simple_shader_program* simple_shader;
light_group* lights;
};
@ -55,15 +58,13 @@ renInit(const char* title = "Tangerine",
void renShutdown(render_state* rs);
render_group*
renAllocateGroup(uint entity_count, shader_program shader);
renAllocateGroup(uint entity_count, shader_wrapper shader);
//
typedef void (*frame_callback_fn) (render_state*);
void renDoRenderLoop(render_state* rs,
uint framerate = 60,
frame_callback_fn cb_func = nullptr);
//
void renRenderFrame(render_state* rs);

36
include/shader_program.h

@ -4,7 +4,7 @@
#include <GL/glew.h>
struct shader_program
struct default_shader_program
{
GLuint program_id;
@ -18,6 +18,36 @@ struct shader_program
GLuint num_lights_id;
};
shader_program* shaderInit(const char* vertex_code, const char* frag_code);
struct simple_shader_program
{
GLuint program_id;
GLuint MVP_id;
GLuint vertex_array_id;
};
enum shader_type
{
SIMPLE_SHADER = 0,
DEFAULT_SHADER = 1
};
struct shader_wrapper
{
shader_type type;
default_shader_program* default_shader;
simple_shader_program* simple_shader;
};
// TODO: find a way to initialize different shaders with different
// uniform layouts with a single function
// look at using uniform blocks and retrieving locations with
// glGetUniformBlockIndex() and their size with glGetActiveUniformBlockiv()
// see chapter 2 in the red book
simple_shader_program*
shaderInitSimple(const char* vertex_code, const char* frag_code);
default_shader_program*
shaderInitDefault(const char* vertex_code, const char* frag_code);
void shaderFree(shader_program* shader);
void shaderFree(uint program_id);

32
src/default_shaders.cpp

@ -13,6 +13,7 @@ uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
fragNormal = normal;
@ -62,3 +63,34 @@ void main()
}
)FS";
const char* SIMPLE_VERTEX_SHADER = R"SVS(
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec3 frag_color;
uniform mat4 MVP;
void main()
{
frag_color = color;
gl_Position = MVP * vec4(position, 1);
}
)SVS";
const char* SIMPLE_FRAGMENT_SHADER = R"SFS(
#version 330 core
in vec3 frag_color;
out vec4 color;
void main()
{
color = vec4(frag_color.rgb, 1);
}
)SFS";

67
src/entity.cpp

@ -10,23 +10,24 @@
// forward declarations
bool loadMeshIntoGL(entity& e);
void initDefaults(entity& e);
bool loadMeshesIntoGL(entity& e);
bool loadSimpleMeshIntoGL(entity& e);
// interface
bool
entInit(entity& e, const char* model_path)
entInitModel(entity& e, const char* model_path)
{
e.world_transform = glm::mat4(1.0);
entScale(e, glm::vec3(1.0));
entSetWorldPosition(e, glm::vec3(0, 0, 0));
initDefaults(e);
e.mesh_type = DEFAULT_MESHES;
if (meLoadFromFile(e.meshes, model_path))
{
e.ro_count = e.meshes.num_meshes;
e.render_objs = UTIL_ALLOC(e.ro_count, render_object);
if (loadMeshIntoGL(e))
if (loadMeshesIntoGL(e))
return true;
}
@ -34,10 +35,40 @@ entInit(entity& e, const char* model_path)
return false;
}
bool
entInitSimpleMesh(entity& e, simple_mesh& mesh, GLenum draw_mode)
{
assert(mesh.num_vertices > 0);
initDefaults(e);
e.mesh_type = SIMPLE_MESH;
e.draw_mode = draw_mode;
e.mesh.num_vertices = mesh.num_vertices;
e.mesh.vertices = UTIL_ALLOC(mesh.num_vertices, glm::vec3);
e.mesh.vert_colors = UTIL_ALLOC(mesh.num_vertices, glm::vec3);
for (uint i = 0; i < mesh.num_vertices; i++) {
e.mesh.vertices[i] = mesh.vertices[i];
e.mesh.vert_colors[i] = mesh.vert_colors[i];
}
if (loadSimpleMeshIntoGL(e))
return true;
entFree(e);
return false;
}
void
entFree(entity& e)
{
meFreeMeshGroup(e.meshes);
if (e.mesh_type == DEFAULT_MESHES)
meFreeMeshGroup(e.meshes);
if (e.mesh_type == SIMPLE_MESH) {
meFreeSimpleMesh(e.mesh);
roFreeSimple(e.simple_ro);
}
for (uint i = 0; i < e.ro_count; i++)
roFree(e.render_objs[i]);
@ -75,8 +106,16 @@ entScale(entity& e, glm::vec3 v)
// internal
void
initDefaults(entity& e)
{
e.world_transform = glm::mat4(1.0);
entScale(e, glm::vec3(1.0));
entSetWorldPosition(e, glm::vec3(0, 0, 0));
}
bool
loadMeshIntoGL(entity& e)
loadMeshesIntoGL(entity& e)
{
for (uint i = 0; i < e.meshes.num_meshes; i++) {
assert(e.render_objs != nullptr);
@ -94,3 +133,15 @@ loadMeshIntoGL(entity& e)
return true;
}
bool
loadSimpleMeshIntoGL(entity& e)
{
assert(e.mesh.num_vertices > 0);
if (roInitSimpleMesh(e.mesh, e.simple_ro))
return true;
LOG(Error) << "Error initializing render object\n";
entFree(e);
return false;
}

2
src/lights.cpp

@ -37,7 +37,7 @@ lightsAdd(light_group* lights, glm::vec3 pos, glm::vec3 color, float intensity)
}
void
lightsUpdate(light_group* lights, shader_program* shader)
lightsUpdate(light_group* lights, default_shader_program* shader)
{
glUniform1ui(shader->num_lights_id, lights->num_lights);

10
src/mesh.cpp

@ -78,6 +78,16 @@ meFreeMeshGroup(mesh_group& mesh_group)
mesh_group.meshes = nullptr;
}
void
meFreeSimpleMesh(simple_mesh& mesh)
{
utilSafeFree(mesh.vertices);
mesh.vertices = nullptr;
utilSafeFree(mesh.vert_colors);
mesh.vert_colors = nullptr;
mesh.num_vertices = 0;
}
void
meShutdownAssimp()
{

61
src/render_object.cpp

@ -11,7 +11,8 @@ bool initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id);
bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id);
bool initGLTexture(const util_image image, GLuint& tex_id);
inline void
updateMatrices(shader_program& shader, camera& cam, glm::mat4 node_xform);
updateMatrices(default_shader_program& shader, camera& cam,
glm::mat4 node_xform);
inline void enableGLFloatBuffer(uint buffer_id, uint location);
@ -44,6 +45,25 @@ roInit(mesh_info* mi_in, render_object& ro_out)
return false;
}
bool
roInitSimpleMesh(simple_mesh& mesh_in, simple_render_object& ro_out)
{
if (initGLFloatBuffer(mesh_in.vertices,
mesh_in.num_vertices,
ro_out.vertex_buffer_id) &&
initGLFloatBuffer(mesh_in.vert_colors,
mesh_in.num_vertices,
ro_out.vertex_color_buffer_id))
{
ro_out.vertex_count = mesh_in.num_vertices;
return true;
}
LOG(Error) << "Failed to initialize render_object\n";
roFreeSimple(ro_out);
return false;
}
void
roFree(render_object& ro)
{
@ -54,10 +74,17 @@ roFree(render_object& ro)
glDeleteTextures(1, &ro.tex_id);
}
void
roFreeSimple(simple_render_object& ro)
{
glDeleteBuffers(1, &ro.vertex_buffer_id);
glDeleteBuffers(1, &ro.vertex_color_buffer_id);
}
void
roDraw(render_object& ro,
camera& cam,
shader_program& shader,
default_shader_program& shader,
light_group* lights)
{
glUseProgram(shader.program_id);
@ -82,6 +109,22 @@ roDraw(render_object& ro,
glUseProgram(0);
}
void
roDrawSimple(simple_render_object& ro,
camera& cam,
simple_shader_program& shader,
GLenum draw_mode)
{
glUseProgram(shader.program_id);
glUniformMatrix4fv(shader.MVP_id, 1, GL_FALSE, &cam.MVP[0][0]);
enableGLFloatBuffer(ro.vertex_buffer_id, 0);
enableGLFloatBuffer(ro.vertex_color_buffer_id, 1);
glDrawArrays(draw_mode, 0, ro.vertex_count);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glUseProgram(0);
}
// internal
bool
@ -129,14 +172,18 @@ initGLTexture(const util_image image, GLuint& tex_id)
// frame, maybe add another interface function in render_object to call from
// renRenderFrame
inline void
updateMatrices(shader_program& shader, camera& cam, glm::mat4 node_xform)
updateMatrices(default_shader_program& shader,
camera& cam,
glm::mat4 node_xform)
{
glUniformMatrix4fv(shader.model_matrix_id, 1, GL_FALSE, &node_xform[0][0]);
glUniformMatrix4fv(shader.view_matrix_id, 1, GL_FALSE, &cam.view[0][0]);
glUniformMatrix4fv(shader.projection_matrix_id, 1, GL_FALSE, &cam.projection[0][0]);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(cam.model)));
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
glUniformMatrix4fv(shader.projection_matrix_id, 1, GL_FALSE,
&cam.projection[0][0]);
glm::mat3 normal_matrix = glm::transpose(
glm::inverse(glm::mat3(cam.model)));
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE,
&normal_matrix[0][0]);
}
inline void

142
src/renderer.cpp

@ -25,14 +25,15 @@
// forward declarations
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam);
bool initSDL(SDL_Handles& handles);
bool createWindow(const char* title,
SDL_Handles& handles,
glm::vec2& viewport_dims);
bool initContext(SDL_Handles& handles);
bool initGlOptions();
bool initSDL(SDL_Handles& handles);
bool initShaders(render_state* rs);
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam);
void setDefaults(render_state* rs, glm::vec2 viewport_dims);
@ -48,17 +49,10 @@ renInit(const char* title, glm::vec2 viewport_dims)
createWindow(title, rs->handles, rs->viewport_dims) &&
initContext(rs->handles) &&
initGlOptions() &&
initShaders(rs) &&
meInitAssimp())
{
rs->default_shader =
shaderInit(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER);
if (rs->default_shader != nullptr) {
return rs;
} else {
LOG(Error) << "shader loading failed\n";
return nullptr;
}
return rs;
}
LOG(Error) << "renderer initialization failed, aborting\n";
@ -68,23 +62,15 @@ renInit(const char* title, glm::vec2 viewport_dims)
void
renShutdown(render_state* rs)
{
// TODO: need a nicer way to loop over entities and render_objects
for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i];
for (uint j = 0; j < rg.entity_count; j++) {
entity& e = rg.entities[j];
for (uint k = 0; k < e.ro_count; k++)
roFree(e.render_objs[k]);
utilSafeFree(e.render_objs);
}
for (uint j = 0; j < rs->render_groups[i].entity_count; j++)
entFree(rs->render_groups[i].entities[j]);
utilSafeFree(rg.entities);
utilSafeFree(rs->render_groups[i].entities);
}
shaderFree(rs->default_shader);
shaderFree(rs->default_shader->program_id);
shaderFree(rs->simple_shader->program_id);
lightsOut(rs->lights);
utilSafeFree(rs->render_groups);
utilSafeFree(rs->default_shader);
@ -95,7 +81,7 @@ renShutdown(render_state* rs)
}
render_group*
renAllocateGroup(uint entity_count, shader_program shader)
renAllocateGroup(uint entity_count, shader_wrapper shader)
{
assert(entity_count > 0);
render_group* rg = UTIL_ALLOC(1, render_group);
@ -137,20 +123,34 @@ renDoRenderLoop(render_state* rs, uint framerate, frame_callback_fn cb_func)
void
renRenderFrame(render_state* rs)
{
glClearColor(rs->clear_col.R, rs->clear_col.G, rs->clear_col.B, rs->clear_col.A);
glClearColor(rs->clear_col.R,
rs->clear_col.G,
rs->clear_col.B,
rs->clear_col.A);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// TODO: need a nicer way to loop over entities and render_objects
// eg) entDraw()
for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i];
for (uint j = 0; j < rg.entity_count; j++) {
entity& e = rg.entities[j];
for (uint k = 0; k < e.ro_count; k++) {
roDraw(e.render_objs[k],
if (rg.shader.type == SIMPLE_SHADER) {
roDrawSimple(e.simple_ro,
rs->cam,
rg.shader,
rs->lights);
*rg.shader.simple_shader,
e.draw_mode);
}
if (rg.shader.type == DEFAULT_SHADER) {
for (uint k = 0; k < e.ro_count; k++) {
roDraw(e.render_objs[k],
rs->cam,
*rg.shader.default_shader,
rs->lights);
}
}
}
}
@ -170,37 +170,6 @@ renAddLight(render_state* rs, glm::vec3 pos, glm::vec3 color, float intensity)
// internal
void
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam)
{
LOG((type == GL_DEBUG_TYPE_ERROR) ? Error : Debug)
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "")
<< ", type: " << type
<< ", severity: " << severity
<< ", message: " << message << "\n";
}
bool
initSDL(SDL_Handles& handles)
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(Error) << "Error, SDL_Init: " << SDL_GetError() << "\n";
return false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode);
return true;
}
bool
createWindow(const char* title, SDL_Handles& handles, glm::vec2& viewport_dims)
{
@ -275,6 +244,55 @@ initGlOptions()
return true;
}
bool
initSDL(SDL_Handles& handles)
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(Error) << "Error, SDL_Init: " << SDL_GetError() << "\n";
return false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode);
return true;
}
bool
initShaders(render_state* rs)
{
rs->default_shader =
shaderInitDefault(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER);
rs->simple_shader =
shaderInitSimple(SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER);
if (rs->default_shader == nullptr ||
rs->simple_shader == nullptr)
{
LOG(Error) << "shader loading failed\n";
return false;
} else {
return true;
}
}
void
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam)
{
LOG((type == GL_DEBUG_TYPE_ERROR) ? Error : Debug)
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "")
<< ", type: " << type
<< ", severity: " << severity
<< ", message: " << message << "\n";
}
void
setDefaults(render_state* rs, glm::vec2 viewport_dims)
{

134
src/shader_program.cpp

@ -4,58 +4,130 @@
#include "util.h"
shader_program*
shaderInit(const char* vertex_code, const char* frag_code)
// forward declarations
bool checkShaderErrors(GLuint program_id);
void cleanUpShader(GLuint program_id, GLuint vs_id, GLuint fs_id);
bool compileProgram(GLuint& program_id_out,
GLuint& vs_id_out,
GLuint& fs_id_out,
const char* vertex_code,
const char* frag_code);
//interface
default_shader_program*
shaderInitDefault(const char* vertex_code, const char* frag_code)
{
shader_program* sp = UTIL_ALLOC(1, shader_program);
default_shader_program* sp = UTIL_ALLOC(1, default_shader_program);
GLuint vs_id = 0;
GLuint fs_id = 0;
compileProgram(sp->program_id, vs_id, fs_id, vertex_code, frag_code);
glGenVertexArrays(1, &sp->vertex_array_id);
glBindVertexArray(sp->vertex_array_id);
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertex_shader_id, 1, &vertex_code, NULL);
glShaderSource(fragment_shader_id, 1, &frag_code, NULL);
glCompileShader(vertex_shader_id);
glCompileShader(fragment_shader_id);
sp->program_id = glCreateProgram();
glAttachShader(sp->program_id, vertex_shader_id);
glAttachShader(sp->program_id, fragment_shader_id);
glLinkProgram(sp->program_id);
// assign uniforms
sp->model_matrix_id = glGetUniformLocation(sp->program_id, "model");
sp->view_matrix_id = glGetUniformLocation(sp->program_id, "view");
sp->projection_matrix_id = glGetUniformLocation(sp->program_id, "projection");
sp->normal_matrix_id = glGetUniformLocation(sp->program_id, "normal_matrix");
sp->projection_matrix_id =
glGetUniformLocation(sp->program_id, "projection");
sp->normal_matrix_id =
glGetUniformLocation(sp->program_id, "normal_matrix");
sp->num_lights_id = glGetUniformLocation(sp->program_id, "num_lights");
sp->sampler_id = glGetUniformLocation(sp->program_id, "sampler");
glDetachShader(sp->program_id, vertex_shader_id);
glDetachShader(sp->program_id, fragment_shader_id);
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
cleanUpShader(sp->program_id, vs_id, fs_id);
if (!checkShaderErrors(sp->program_id)) {
glDeleteProgram(sp->program_id);
return nullptr;
}
return sp;
}
simple_shader_program*
shaderInitSimple(const char* vertex_code, const char* frag_code)
{
simple_shader_program* sp = UTIL_ALLOC(1, simple_shader_program);
GLuint vs_id = 0;
GLuint fs_id = 0;
compileProgram(sp->program_id, vs_id, fs_id, vertex_code, frag_code);
// TODO: add to compile program?
glGenVertexArrays(1, &sp->vertex_array_id);
glBindVertexArray(sp->vertex_array_id);
if (!checkShaderErrors(sp->program_id)) {
glDeleteProgram(sp->program_id);
return nullptr;
}
return sp;
}
void
shaderFree(uint program_id)
{
// TODO: can check for valid id here
glDeleteProgram(program_id);
}
// internal
bool
checkShaderErrors(uint program_id)
{
GLint isLinked = 0;
glGetProgramiv(sp->program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
GLint info_len = 0;
glGetProgramiv(sp->program_id, GL_INFO_LOG_LENGTH, &info_len);
GLint info_len = 0;
glGetProgramiv(program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_len);
char* infoLog = UTIL_ALLOC(info_len, char);
glGetProgramInfoLog(sp->program_id, info_len, &info_len, &infoLog[0]);
glGetProgramInfoLog(program_id, info_len, &info_len, &infoLog[0]);
LOG(Error) << infoLog << "\n";
utilSafeFree(infoLog);
glDeleteProgram(program_id);
glDeleteProgram(sp->program_id);
return nullptr;
return false;
}
return sp;
return true;
}
void
shaderFree(shader_program* shader)
cleanUpShader(GLuint program_id, GLuint vs_id, GLuint fs_id)
{
glDetachShader(program_id, vs_id);
glDetachShader(program_id, fs_id);
glDeleteShader(vs_id);
glDeleteShader(fs_id);
}
bool
compileProgram(GLuint& program_id_out,
GLuint& vs_id_out,
GLuint& fs_id_out,
const char* vertex_code,
const char* frag_code)
{
glDeleteProgram(shader->program_id);
vs_id_out = glCreateShader(GL_VERTEX_SHADER);
fs_id_out = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs_id_out, 1, &vertex_code, NULL);
glShaderSource(fs_id_out, 1, &frag_code, NULL);
glCompileShader(vs_id_out);
glCompileShader(fs_id_out);
// TODO: can check for error here
program_id_out = glCreateProgram();
glAttachShader(program_id_out, vs_id_out);
glAttachShader(program_id_out, fs_id_out);
glLinkProgram(program_id_out);
// TODO: can check for error here
return true;
}

Loading…
Cancel
Save