Browse Source

adding fancy lighting

master
cinnaboot 8 years ago
parent
commit
2fd9f39871
  1. 17
      data/default.fs
  2. 11
      data/default.vs
  3. 4
      src/gooey.cpp
  4. 8
      src/hexgame.cpp
  5. 2
      src/hexgame.h
  6. 1
      src/mesh.h
  7. 30
      src/render_group.cpp
  8. 7
      src/render_group.h
  9. 50
      src/renderer.cpp
  10. 14
      src/renderer.h
  11. 2
      src/util.cpp

17
data/default.fs

@ -1,11 +1,26 @@
#version 330 core #version 330 core
in vec3 fragmentColor; in vec3 fragmentColor;
in vec3 fragNormal;
in vec3 fragVertex;
uniform mat4 model;
uniform vec3 light_position;
uniform mat3 normal_matrix;
out vec3 color; out vec3 color;
void main() void main()
{ {
color = fragmentColor; // https://www.tomdalling.com/blog/modern-opengl/06-diffuse-point-lighting
vec3 normal = normalize(normal_matrix * fragNormal);
vec3 fragPosition = vec3(model * vec4(fragVertex, 1));
vec3 surfaceToLight = light_position - fragPosition;
float brightness = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
brightness = clamp(brightness, 0, 1);
color = brightness * fragmentColor;
} }

11
data/default.vs

@ -1,9 +1,12 @@
#version 330 core #version 330 core
in vec3 vertexPosition_modelspace; layout (location = 0) in vec3 vertexPosition_modelspace;
in vec3 vertexColor; layout (location = 1) in vec3 vertexColor;
layout (location = 2) in vec3 normal;
out vec3 fragmentColor; out vec3 fragmentColor;
out vec3 fragNormal;
out vec3 fragVertex;
uniform mat4 model; uniform mat4 model;
uniform mat4 view; uniform mat4 view;
@ -11,7 +14,9 @@ uniform mat4 projection;
void main() void main()
{ {
gl_Position = projection * view * model * vec4(vertexPosition_modelspace, 1);
fragmentColor = vertexColor; fragmentColor = vertexColor;
fragNormal = normal;
fragVertex = vertexPosition_modelspace;
gl_Position = projection * view * model * vec4(vertexPosition_modelspace, 1);
} }

4
src/gooey.cpp

@ -79,8 +79,8 @@ renderGooey(SDL_Handles &handles, HexDrawMode &mode, bool &is_debug,
if (ImGui::CollapsingHeader("Camera Position")) { if (ImGui::CollapsingHeader("Camera Position")) {
ImGui::Text("x: %f", camera_pos.x); ImGui::Text("x: %f", camera_pos.x);
ImGui::Text("x: %f", camera_pos.y); ImGui::Text("y: %f", camera_pos.y);
ImGui::Text("x: %f", camera_pos.z); ImGui::Text("z: %f", camera_pos.z);
} }
#if 0 #if 0

8
src/hexgame.cpp

@ -1,11 +1,15 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TODO: // TODO:
// - lighting // - lighting
// - add light struct
// - pass all lights to render groups/shaders every frame
// - need to give hexagons vertex normals (can then get rid of rgDraw())
// - maybe use more than one model in a scene
// - map generation // - map generation
// - pathfinding // - pathfinding
// - assimp animation // - assimp animation
// - update imgui to v1.62 -- requires changes to example api // - update imgui to v1.62 -- requires changes to example api
// - replace aixlog with custom logging iostream // - replace aixlog with custom logging iostream?
// - fix vector normalization in renderer.cpp when moving in 2 directions // - fix vector normalization in renderer.cpp when moving in 2 directions
// - add prefix to interface function names for eg) gooey.h, renderer.h // - add prefix to interface function names for eg) gooey.h, renderer.h
// - test build on windows / update vs project files // - test build on windows / update vs project files
@ -565,8 +569,10 @@ int main(int argc, char* argv[])
g->is_moveforward, g->is_movebackward); g->is_moveforward, g->is_movebackward);
rollCamera(g->is_rotateCW, g->is_rotateCCW); rollCamera(g->is_rotateCW, g->is_rotateCCW);
renderFrame(g->hex_array, g_render_state->entities, g_render_state->entity_count); renderFrame(g->hex_array, g_render_state->entities, g_render_state->entity_count);
#if 0
if (r->is_debug_draw && g->draw_mode == CONE_FILL) if (r->is_debug_draw && g->draw_mode == CONE_FILL)
renderDebug(g_polygon_select_vertices); renderDebug(g_polygon_select_vertices);
#endif
renderGooey(handles, g->draw_mode, r->is_debug_draw, g->start_hex, renderGooey(handles, g->draw_mode, r->is_debug_draw, g->start_hex,
g->current_hex, g->is_selecting, getCameraPosition()); g->current_hex, g->is_selecting, getCameraPosition());
SDL_GL_SwapWindow(handles.window); SDL_GL_SwapWindow(handles.window);

2
src/hexgame.h

@ -9,7 +9,7 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#endif #endif
#include <glm/glm.hpp> // vec3 #include <glm/glm.hpp>
#include "hexlib.h" #include "hexlib.h"
#include "util.h" #include "util.h"

1
src/mesh.h

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <glm/glm.hpp>
struct meMeshInfo struct meMeshInfo
{ {

30
src/render_group.cpp

@ -43,6 +43,7 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
rg->model_matrix_id = glGetUniformLocation(rg->program_id, model_name); rg->model_matrix_id = glGetUniformLocation(rg->program_id, model_name);
rg->view_matrix_id = glGetUniformLocation(rg->program_id, view_name); rg->view_matrix_id = glGetUniformLocation(rg->program_id, view_name);
rg->projection_matrix_id = glGetUniformLocation(rg->program_id, projection_name); rg->projection_matrix_id = glGetUniformLocation(rg->program_id, projection_name);
rg->normal_matrix_id = glGetUniformLocation(rg->program_id, "normal_matrix");
glDetachShader(rg->program_id, vertex_shader_id); glDetachShader(rg->program_id, vertex_shader_id);
glDetachShader(rg->program_id, fragment_shader_id); glDetachShader(rg->program_id, fragment_shader_id);
@ -73,6 +74,7 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
void void
rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[]) rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[])
{ {
// TODO: why not just assing the pointer to the render group instead of copying here?
buf_obj->buffer_len = len; buf_obj->buffer_len = len;
buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat));
@ -201,23 +203,31 @@ rgInitEntity(gl_render_group* rg, Entity* e)
void void
rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data) glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id)
{ {
glUseProgram(rg->program_id); glUseProgram(rg->program_id);
glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]);
glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]);
glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]);
// TODO: testing lighting
glUniform3f(light_id, light_position.x, light_position.y, light_position.z);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix)));
glUniformMatrix3fv(rg->normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
// 1st attribute buffer : vertices // 1st attribute buffer : vertices
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
#if 0
if (update_vertex_data) if (update_vertex_data)
{ {
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat), glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat),
rg->vertex_buffer.buffer); rg->vertex_buffer.buffer);
} }
#endif
// 2nd attribute buffer : colors // 2nd attribute buffer : colors
if (rg->color_buffer.buffer) if (rg->color_buffer.buffer)
@ -230,6 +240,14 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat),
rg->color_buffer.buffer); rg->color_buffer.buffer);
} }
// 3rd attribute buffer: normals
if (rg->use_normals) {
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
}
// draw // draw
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3);
@ -241,12 +259,18 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
void void
rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data) glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id)
{ {
glUseProgram(rg->program_id); glUseProgram(rg->program_id);
glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]);
glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]);
glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]);
// TODO: testing lighting
glUniform3f(light_id, light_position.x, light_position.y, light_position.z);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix)));
glUniformMatrix3fv(rg->normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
// 1st attribute buffer : vertices // 1st attribute buffer : vertices
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
@ -300,6 +324,8 @@ rgFree(gl_render_group* rg)
rg->index_buffer.indices = nullptr; rg->index_buffer.indices = nullptr;
} }
// TODO: free vertex_normals here, and switch to using utilFree function
std::free(rg); std::free(rg);
rg = nullptr; rg = nullptr;
} }

7
src/render_group.h

@ -28,6 +28,7 @@ struct gl_render_group
GLuint model_matrix_id = 0; GLuint model_matrix_id = 0;
GLuint view_matrix_id = 0; GLuint view_matrix_id = 0;
GLuint projection_matrix_id = 0; GLuint projection_matrix_id = 0;
GLuint normal_matrix_id = 0;
GLuint vertex_array_id = 0; GLuint vertex_array_id = 0;
bool use_normals = false; bool use_normals = false;
}; };
@ -50,10 +51,12 @@ bool rgInitEntity(gl_render_group* rg, Entity* e);
void rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes); void rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes);
void rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, void rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data = false); glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id);
void rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, void rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data = false); glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id);
void rgFree(gl_render_group* rg); void rgFree(gl_render_group* rg);

50
src/renderer.cpp

@ -90,6 +90,10 @@ gl_render_group* g_entity_render_group = rgCreateGroup();
camera g_camera; camera g_camera;
// TODO: testing lighting
renPointLight g_test_light;
bool bool
addTexture(SDL_Handles &handles, const char * path) addTexture(SDL_Handles &handles, const char * path)
{ {
@ -375,7 +379,7 @@ createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
int hex_count = (int) hexes->size(); int hex_count = (int) hexes->size();
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
int vbuf_len = hex_count * 6 * 3 * 3; int vbuf_len = hex_count * 6 * 3 * 3;
// TODO: surely there's a way to use indexed drawing for line vertices eg) line_loop // TODO: surely there's a way to use indexed drawing for line vertices eg) line_loop
// and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements? // and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements?
// https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index // https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index
@ -389,19 +393,31 @@ createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
for (int i = 0; i < hex_count; i++) for (int i = 0; i < hex_count; i++)
fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]); fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]);
rgInitGLBufferObject(&g_filled_hex_render_group->vertex_buffer, vbuf_len, rgInitGLBufferObject(&g_filled_hex_render_group->vertex_buffer, vbuf_len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vbuf); GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vbuf);
// color data for hex vertices // color data for hex vertices
rgFillColorBuffer(cbuf, vbuf_len, hexes); rgFillColorBuffer(cbuf, vbuf_len, hexes);
rgInitGLBufferObject(&g_filled_hex_render_group->color_buffer, vbuf_len, rgInitGLBufferObject(&g_filled_hex_render_group->color_buffer, vbuf_len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, cbuf); GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, cbuf);
// hex line vertex data // cheat at vertex normals since all hexes lay flat on z-axis
GLfloat* normal_buf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat));
for (int i = 0; i < vbuf_len; i += 3) {
normal_buf[i] = 0;
normal_buf[i + 1] = 0;
normal_buf[i + 2] = 1;
}
rgInitGLBufferObject(&g_filled_hex_render_group->vertex_normals, vbuf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf);
g_filled_hex_render_group->use_normals = true;
// hex line vertex data
fillHexLineBuffer(line_buf, line_buf_len, hexes); fillHexLineBuffer(line_buf, line_buf_len, hexes);
rgInitGLBufferObject(&g_hex_line_render_group->vertex_buffer, line_buf_len, rgInitGLBufferObject(&g_hex_line_render_group->vertex_buffer, line_buf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, line_buf); GL_STATIC_DRAW, GL_ARRAY_BUFFER, line_buf);
@ -412,7 +428,8 @@ createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
std::free(vbuf); std::free(vbuf);
std::free(cbuf); std::free(cbuf);
std::free(line_buf); std::free(line_buf);
vbuf = cbuf = line_buf = nullptr; std::free(normal_buf);
vbuf = cbuf = line_buf = normal_buf = nullptr;
// debug draw vertexes // debug draw vertexes
int len = 4 * 3; // 4 vertices, 3 floats per vertex int len = 4 * 3; // 4 vertices, 3 floats per vertex
@ -421,9 +438,20 @@ createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
// entities // entities
// TODO: wtf, I only accounted for 1 entity in the entity render group :(
// probably need one render_group struct for each entity
for (uint i = 0; i < entity_count; i++) for (uint i = 0; i < entity_count; i++)
rgInitEntity(g_entity_render_group, &entities[i]); rgInitEntity(g_entity_render_group, &entities[i]);
// lights
// TODO: load light properties from scene/level files
g_test_light.light_ID = glGetUniformLocation(g_entity_render_group->program_id, "light_position");
g_test_light.position = glm::vec3(640, 500, 400); // above center of hexgrid
g_test_light.direction = glm::vec3(0, 0, 0) - g_test_light.position; // back towards test entity
g_test_light.color = glm::vec3(1.f, 1.f, 1.f);
g_test_light.intensity = 1.f;
return true; return true;
} }
@ -527,21 +555,26 @@ renderFrame(std::vector<hex_info> *hexes, Entity* entities, uint32 entity_count)
// get new colors every frame // get new colors every frame
gl_render_group* rg = g_filled_hex_render_group; gl_render_group* rg = g_filled_hex_render_group;
rgFillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); rgFillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes);
rgDraw(rg, GL_TRIANGLES, m_model, m_view, m_projection); rgDraw(rg, GL_TRIANGLES, m_model, m_view, m_projection,
g_test_light.position, g_test_light.light_ID);
// hex lines // hex lines
rgDraw(g_hex_line_render_group, GL_LINES, m_model, m_view, m_projection); //rgDraw(g_hex_line_render_group, GL_LINES, m_model, m_view, m_projection);
// TODO: update and send array of lights (pos, dir, color, intesity to shaders
// every frame through rgDrawIndexed()
// entities // entities
for (uint i = 0; i < entity_count; i++) { for (uint i = 0; i < entity_count; i++) {
rgDrawIndexed( rgDrawIndexed(
g_entity_render_group, GL_TRIANGLES, g_entity_render_group, GL_TRIANGLES,
entities[i].mesh->model_transform, m_view, m_projection entities[i].mesh->model_transform, m_view, m_projection,
g_test_light.position, g_test_light.light_ID
); );
} }
} }
#if 0
void void
renderDebug(std::vector<Point> &vertices) renderDebug(std::vector<Point> &vertices)
{ {
@ -561,6 +594,7 @@ renderDebug(std::vector<Point> &vertices)
rgDraw(rg, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view, rgDraw(rg, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view,
g_scene_matrices.projection, true); g_scene_matrices.projection, true);
} }
#endif
void void
freeBuffers() freeBuffers()

14
src/renderer.h

@ -3,9 +3,21 @@
#include <vector> #include <vector>
#include <glm/glm.hpp>
#include "util.h" #include "util.h"
#include "hexgame.h" #include "hexgame.h"
struct renPointLight
{
glm::vec3 position;
glm::vec3 direction;
glm::vec3 color;
float intensity;
uint light_ID;
};
bool initRenderer(SDL_Handles &handles, v2i vpDims); bool initRenderer(SDL_Handles &handles, v2i vpDims);
bool addTexture(SDL_Handles &handles, const char * path); bool addTexture(SDL_Handles &handles, const char * path);
v2f getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height); v2f getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height);
@ -15,6 +27,6 @@ void moveCamera(bool up, bool left, bool down, bool right, bool forward, bool ba
void rollCamera(bool CW, bool CCW); void rollCamera(bool CW, bool CCW);
void rotateCamera(int32 xrel, int32 yrel); void rotateCamera(int32 xrel, int32 yrel);
void renderFrame(std::vector<hex_info> *hexes, Entity* entities, uint32 entity_count); void renderFrame(std::vector<hex_info> *hexes, Entity* entities, uint32 entity_count);
void renderDebug(std::vector<Point> &vertices); //void renderDebug(std::vector<Point> &vertices);
void freeBuffers(); void freeBuffers();

2
src/util.cpp

@ -29,7 +29,7 @@ utilDumpTextFile(const char* filename)
return buf; return buf;
} }
// TODO: search/replace other calls to stdd::free with this // TODO: search/replace other calls to std::free with this
void void
utilSafeFree(void* mem) utilSafeFree(void* mem)
{ {

Loading…
Cancel
Save