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 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 .PHONY: all
-include $(OBJDIR)/*.d -include $(OBJDIR)/*.d
@ -24,6 +27,10 @@ $(OBJDIR)/assimp_loading.o: $(LIB)
$(CXX) $(CXXFLAGS) -c -MMD assimp_loading/main.cpp -o $@ $(CXX) $(CXXFLAGS) -c -MMD assimp_loading/main.cpp -o $@
$(CXX) -o $(BINDIR)/assimp_loading $(LDFLAGS) $@ $(LIB) $(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: clean:
rm -rf $(OBJDIR)/* bin/* rm -rf $(OBJDIR)/* bin/*
.PHONY: clean .PHONY: clean

8
examples/assimp_loading/main.cpp

@ -4,8 +4,9 @@
#include "camera.h" #include "camera.h"
#include "dumbLog.h" #include "dumbLog.h"
#include "renderer.h"
#include "entity.h" #include "entity.h"
#include "renderer.h"
#include "shader_program.h"
void void
@ -27,7 +28,8 @@ main()
} }
// TODO: this needs to be more convenient // 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; rs->render_group_count = 1;
entity& spaceship = rs->render_groups->entities[0]; entity& spaceship = rs->render_groups->entities[0];
@ -48,7 +50,7 @@ main()
// NOTE: testing assimp animation info // NOTE: testing assimp animation info
logDebugAnimationInfo("../data/spaceship.glb"); logDebugAnimationInfo("../data/spaceship.glb");
if (entInit(spaceship, "../data/spaceship.glb")) { if (entInitModel(spaceship, "../data/spaceship.glb")) {
// TODO: this should be handled in entInit // TODO: this should be handled in entInit
entSetWorldPosition(spaceship, glm::vec3(0, 0, 0)); entSetWorldPosition(spaceship, glm::vec3(0, 0, 0));
entScale(spaceship, glm::vec3(20, 20, 20)); 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" #include "render_object.h"
enum mesh_group_type
{
DEFAULT_MESHES = 0,
SIMPLE_MESH = 1
};
struct entity struct entity
{ {
glm::mat4 world_transform; 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 // TODO: should be a pointer into a global array of mesh_info(s) or
// mesh_groups stored on the render_state object // mesh_groups stored on the render_state object
mesh_group meshes; mesh_group meshes;
render_object* render_objs; render_object* render_objs;
uint ro_count; 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); void entFree(entity& e);

2
include/lights.h

@ -30,5 +30,5 @@ void lightsOut(light_group* lights);
bool bool
lightsAdd(light_group* lights, glm::vec3 pos, glm::vec3 color, float intensity); 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; uint num_meshes;
}; };
struct simple_mesh
{
glm::vec3* vertices;
glm::vec3* vert_colors;
uint num_vertices;
};
bool meInitAssimp(); bool meInitAssimp();
@ -43,5 +50,7 @@ bool meLoadFromFile(mesh_group& mesh_group, const char* filepath);
void meFreeMeshGroup(mesh_group& mesh_group); void meFreeMeshGroup(mesh_group& mesh_group);
void meFreeSimpleMesh(simple_mesh& mesh);
void meShutdownAssimp(); void meShutdownAssimp();

21
include/render_object.h

@ -19,14 +19,31 @@ struct render_object
GLuint normal_buffer_id; GLuint normal_buffer_id;
GLuint uv_buffer_id; GLuint uv_buffer_id;
GLuint index_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 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 roFree(render_object& ro);
void roFreeSimple(simple_render_object& ro);
void roDraw(render_object& ro, void roDraw(render_object& ro,
camera& cam, camera& cam,
shader_program& shader, default_shader_program& shader,
light_group* lights); 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 // NOTE: array of entities rendered with the same shader program
struct render_group struct render_group
{ {
// TODO: also needs to be resizable
entity* entities; entity* entities;
uint entity_count; uint entity_count;
shader_program shader; shader_wrapper shader;
}; };
struct render_state struct render_state
@ -44,7 +45,9 @@ struct render_state
render_group* render_groups; render_group* render_groups;
uint render_group_count; uint render_group_count;
shader_program* default_shader; default_shader_program* default_shader;
simple_shader_program* simple_shader;
light_group* lights; light_group* lights;
}; };
@ -55,15 +58,13 @@ renInit(const char* title = "Tangerine",
void renShutdown(render_state* rs); void renShutdown(render_state* rs);
render_group* render_group*
renAllocateGroup(uint entity_count, shader_program shader); renAllocateGroup(uint entity_count, shader_wrapper shader);
//
typedef void (*frame_callback_fn) (render_state*); typedef void (*frame_callback_fn) (render_state*);
void renDoRenderLoop(render_state* rs, void renDoRenderLoop(render_state* rs,
uint framerate = 60, uint framerate = 60,
frame_callback_fn cb_func = nullptr); frame_callback_fn cb_func = nullptr);
//
void renRenderFrame(render_state* rs); void renRenderFrame(render_state* rs);

36
include/shader_program.h

@ -4,7 +4,7 @@
#include <GL/glew.h> #include <GL/glew.h>
struct shader_program struct default_shader_program
{ {
GLuint program_id; GLuint program_id;
@ -18,6 +18,36 @@ struct shader_program
GLuint num_lights_id; 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 view;
uniform mat4 projection; uniform mat4 projection;
void main() void main()
{ {
fragNormal = normal; fragNormal = normal;
@ -62,3 +63,34 @@ void main()
} }
)FS"; )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 // forward declarations
bool loadMeshIntoGL(entity& e); void initDefaults(entity& e);
bool loadMeshesIntoGL(entity& e);
bool loadSimpleMeshIntoGL(entity& e);
// interface // interface
bool bool
entInit(entity& e, const char* model_path) entInitModel(entity& e, const char* model_path)
{ {
e.world_transform = glm::mat4(1.0); initDefaults(e);
entScale(e, glm::vec3(1.0)); e.mesh_type = DEFAULT_MESHES;
entSetWorldPosition(e, glm::vec3(0, 0, 0));
if (meLoadFromFile(e.meshes, model_path)) if (meLoadFromFile(e.meshes, model_path))
{ {
e.ro_count = e.meshes.num_meshes; e.ro_count = e.meshes.num_meshes;
e.render_objs = UTIL_ALLOC(e.ro_count, render_object); e.render_objs = UTIL_ALLOC(e.ro_count, render_object);
if (loadMeshIntoGL(e)) if (loadMeshesIntoGL(e))
return true; return true;
} }
@ -34,10 +35,40 @@ entInit(entity& e, const char* model_path)
return false; 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 void
entFree(entity& e) 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++) for (uint i = 0; i < e.ro_count; i++)
roFree(e.render_objs[i]); roFree(e.render_objs[i]);
@ -75,8 +106,16 @@ entScale(entity& e, glm::vec3 v)
// internal // 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 bool
loadMeshIntoGL(entity& e) loadMeshesIntoGL(entity& e)
{ {
for (uint i = 0; i < e.meshes.num_meshes; i++) { for (uint i = 0; i < e.meshes.num_meshes; i++) {
assert(e.render_objs != nullptr); assert(e.render_objs != nullptr);
@ -94,3 +133,15 @@ loadMeshIntoGL(entity& e)
return true; 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 void
lightsUpdate(light_group* lights, shader_program* shader) lightsUpdate(light_group* lights, default_shader_program* shader)
{ {
glUniform1ui(shader->num_lights_id, lights->num_lights); 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; 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 void
meShutdownAssimp() 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 initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id);
bool initGLTexture(const util_image image, GLuint& tex_id); bool initGLTexture(const util_image image, GLuint& tex_id);
inline void 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); inline void enableGLFloatBuffer(uint buffer_id, uint location);
@ -44,6 +45,25 @@ roInit(mesh_info* mi_in, render_object& ro_out)
return false; 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 void
roFree(render_object& ro) roFree(render_object& ro)
{ {
@ -54,10 +74,17 @@ roFree(render_object& ro)
glDeleteTextures(1, &ro.tex_id); 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 void
roDraw(render_object& ro, roDraw(render_object& ro,
camera& cam, camera& cam,
shader_program& shader, default_shader_program& shader,
light_group* lights) light_group* lights)
{ {
glUseProgram(shader.program_id); glUseProgram(shader.program_id);
@ -82,6 +109,22 @@ roDraw(render_object& ro,
glUseProgram(0); 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 // internal
bool 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 // frame, maybe add another interface function in render_object to call from
// renRenderFrame // renRenderFrame
inline void 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.model_matrix_id, 1, GL_FALSE, &node_xform[0][0]);
glUniformMatrix4fv(shader.view_matrix_id, 1, GL_FALSE, &cam.view[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]); glUniformMatrix4fv(shader.projection_matrix_id, 1, GL_FALSE,
&cam.projection[0][0]);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(cam.model))); glm::mat3 normal_matrix = glm::transpose(
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); glm::inverse(glm::mat3(cam.model)));
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE,
&normal_matrix[0][0]);
} }
inline void inline void

142
src/renderer.cpp

@ -25,14 +25,15 @@
// forward declarations // 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, bool createWindow(const char* title,
SDL_Handles& handles, SDL_Handles& handles,
glm::vec2& viewport_dims); glm::vec2& viewport_dims);
bool initContext(SDL_Handles& handles); bool initContext(SDL_Handles& handles);
bool initGlOptions(); 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); 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) && createWindow(title, rs->handles, rs->viewport_dims) &&
initContext(rs->handles) && initContext(rs->handles) &&
initGlOptions() && initGlOptions() &&
initShaders(rs) &&
meInitAssimp()) meInitAssimp())
{ {
rs->default_shader = return rs;
shaderInit(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER);
if (rs->default_shader != nullptr) {
return rs;
} else {
LOG(Error) << "shader loading failed\n";
return nullptr;
}
} }
LOG(Error) << "renderer initialization failed, aborting\n"; LOG(Error) << "renderer initialization failed, aborting\n";
@ -68,23 +62,15 @@ renInit(const char* title, glm::vec2 viewport_dims)
void void
renShutdown(render_state* rs) 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++) { for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i]; for (uint j = 0; j < rs->render_groups[i].entity_count; j++)
entFree(rs->render_groups[i].entities[j]);
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);
}
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); lightsOut(rs->lights);
utilSafeFree(rs->render_groups); utilSafeFree(rs->render_groups);
utilSafeFree(rs->default_shader); utilSafeFree(rs->default_shader);
@ -95,7 +81,7 @@ renShutdown(render_state* rs)
} }
render_group* render_group*
renAllocateGroup(uint entity_count, shader_program shader) renAllocateGroup(uint entity_count, shader_wrapper shader)
{ {
assert(entity_count > 0); assert(entity_count > 0);
render_group* rg = UTIL_ALLOC(1, render_group); render_group* rg = UTIL_ALLOC(1, render_group);
@ -137,20 +123,34 @@ renDoRenderLoop(render_state* rs, uint framerate, frame_callback_fn cb_func)
void void
renRenderFrame(render_state* rs) 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); 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++) { for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i]; render_group& rg = rs->render_groups[i];
for (uint j = 0; j < rg.entity_count; j++) { for (uint j = 0; j < rg.entity_count; j++) {
entity& e = rg.entities[j]; entity& e = rg.entities[j];
for (uint k = 0; k < e.ro_count; k++) { if (rg.shader.type == SIMPLE_SHADER) {
roDraw(e.render_objs[k], roDrawSimple(e.simple_ro,
rs->cam, rs->cam,
rg.shader, *rg.shader.simple_shader,
rs->lights); 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 // 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 bool
createWindow(const char* title, SDL_Handles& handles, glm::vec2& viewport_dims) createWindow(const char* title, SDL_Handles& handles, glm::vec2& viewport_dims)
{ {
@ -275,6 +244,55 @@ initGlOptions()
return true; 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 void
setDefaults(render_state* rs, glm::vec2 viewport_dims) setDefaults(render_state* rs, glm::vec2 viewport_dims)
{ {

134
src/shader_program.cpp

@ -4,58 +4,130 @@
#include "util.h" #include "util.h"
shader_program* // forward declarations
shaderInit(const char* vertex_code, const char* frag_code) 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); glGenVertexArrays(1, &sp->vertex_array_id);
glBindVertexArray(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->model_matrix_id = glGetUniformLocation(sp->program_id, "model");
sp->view_matrix_id = glGetUniformLocation(sp->program_id, "view"); sp->view_matrix_id = glGetUniformLocation(sp->program_id, "view");
sp->projection_matrix_id = glGetUniformLocation(sp->program_id, "projection"); sp->projection_matrix_id =
sp->normal_matrix_id = glGetUniformLocation(sp->program_id, "normal_matrix"); 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->num_lights_id = glGetUniformLocation(sp->program_id, "num_lights");
sp->sampler_id = glGetUniformLocation(sp->program_id, "sampler"); sp->sampler_id = glGetUniformLocation(sp->program_id, "sampler");
glDetachShader(sp->program_id, vertex_shader_id); cleanUpShader(sp->program_id, vs_id, fs_id);
glDetachShader(sp->program_id, fragment_shader_id);
glDeleteShader(vertex_shader_id); if (!checkShaderErrors(sp->program_id)) {
glDeleteShader(fragment_shader_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; GLint isLinked = 0;
glGetProgramiv(sp->program_id, GL_LINK_STATUS, &isLinked); GLint info_len = 0;
if (isLinked == GL_FALSE) { glGetProgramiv(program_id, GL_LINK_STATUS, &isLinked);
GLint info_len = 0;
glGetProgramiv(sp->program_id, GL_INFO_LOG_LENGTH, &info_len);
if (isLinked == GL_FALSE) {
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_len);
char* infoLog = UTIL_ALLOC(info_len, char); 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"; LOG(Error) << infoLog << "\n";
utilSafeFree(infoLog); utilSafeFree(infoLog);
glDeleteProgram(program_id);
glDeleteProgram(sp->program_id); return false;
return nullptr;
} }
return sp; return true;
} }
void 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