Browse Source

break out shader specific functions to separate file

main
cinnaboot 5 years ago
parent
commit
8e0ee5411c
  1. 2
      Makefile
  2. 2
      src/dumpShader.inl
  3. 527
      src/main.cpp
  4. 262
      src/shader.cpp
  5. 35
      src/shader.h

2
Makefile

@ -1,7 +1,7 @@
SHELL = /bin/sh
CXX = g++
CXXFLAGS = -std=c++11 -g -ggdb3 -Wall -Isrc/ -I/usr/include/SDL2
CXXFLAGS = -std=c++11 -g -ggdb3 -Og -Wall -Isrc/ -I/usr/include/SDL2
LDFLAGS = -lSDL2 -lGLEW -lGL
OBJDIR = build
SRCDIR = src

2
src/dumpShader.inl

@ -1,7 +1,7 @@
#include <GL/glew.h>
#include "shader_testing.h"
#include "shader.h"
const char* gl_enum_to_string(GLenum e);

527
src/main.cpp

@ -1,198 +1,13 @@
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <string>
#include <fstream>
#include <iostream>
#include <SDL2/SDL.h>
#include <glm/geometric.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "asset.h"
#include "shader_testing.h"
#include "shader.h"
#include "dumpShader.inl"
const float DEFAULT_FOV = 60.f;
const float NEAR_CLIP_PLANE = 5.f;
const float DEFAULT_ASPECT_RATIO = 16.f / 9.f;
const glm::vec3 DEFAULT_CAM_POS = { 0, 0, -30.f };
const glm::vec3 DEFAULT_LOOK_POS = { 0, 0, 0 };
SDL_Window *g_window = 0;
SDL_GLContext g_glContext;
SDL_DisplayMode g_display_mode;
void
openglDebugCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam)
{
std::cout << ((type == GL_DEBUG_TYPE_ERROR) ? "Error" : "Debug")
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "")
<< ", type: " << type
<< ", severity: " << severity
<< ", message: " << message << "\n";
}
bool
initGraphics()
{
g_window = SDL_CreateWindow(
"shader_testing",
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
1280,
720,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "error, sdl init: " << SDL_GetError() << "\n";
return false;
}
SDL_GL_SetSwapInterval(1);
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, &g_display_mode);
g_glContext = SDL_GL_CreateContext(g_window);
if (!g_glContext) {
std::cout << "error creating context\n";
return false;
}
if (glewInit()) {
std::cout << "error initializing opengl\n";
return false;
}
std::cout << "opengl vendor: " << glGetString(GL_VENDOR) << "\n";
std::cout << "opengl renderer: " << glGetString(GL_RENDERER) << "\n";
std::cout << "opengl version: " << glGetString(GL_VERSION) << "\n";
glEnable(GL_DEPTH_TEST);
glEnable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable (GL_DEBUG_OUTPUT);
glDebugMessageCallback((GLDEBUGPROC) openglDebugCallback, 0);
return g_window != nullptr;
}
const std::string
dumpTextFile(const char* filepath)
{
std::ifstream fs { filepath };
std::string s {
std::istreambuf_iterator<char>(fs),
std::istreambuf_iterator<char>()};
if (!fs || !fs.good())
std::cout << "error reading file, " << filepath << "\n";
return s;
}
void
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx)
{
GLint unif_count;
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORMS, &unif_count);
s->num_uniforms = unif_count;
s->uniforms = (gl_uniform*) arenaAllocateBlock(
arena, s->num_uniforms * sizeof(gl_uniform));
for (u32 i = 0; i < s->num_uniforms; i++) {
GLchar unif_name[256] = {0};
GLsizei length;
GLint size;
GLenum type;
glGetActiveUniform(s->prog_id, i, sizeof(unif_name),
&length, &size, &type, unif_name);
s->uniforms[i].data_type = type;
s->uniforms[i].name = (char*) arenaAllocateBlock(
arena, (length + 1) * sizeof(char));
std::strncpy(s->uniforms[i].name, unif_name, length);
glGetActiveUniformsiv(s->prog_id, 1, &i,
GL_UNIFORM_BLOCK_INDEX, &s->uniforms[i].block_idx);
// FIXME: testing idx == unif location
s->uniforms[i].idx = i;
GLuint location = glGetUniformLocation(s->prog_id, s->uniforms[i].name);
printf("idx: %d, loc: %d, block idx: %d \n",
i, location, s->uniforms[i].block_idx);
// TODO: get uniform.data_size from data_type
//printf("i: %d, uniform name: %s, l: %d \n", i, unif_name, length);
}
GLint max_vert_ublocks;
GLint max_frag_ublocks;
GLint max_ublock_size;
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &max_vert_ublocks);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &max_frag_ublocks);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ublock_size);
printf("max vert uniform blocks: %d, max frag uniform blocks: %d,"
"max uniform block size: %d bytes \n",
max_vert_ublocks, max_frag_ublocks, max_ublock_size);
GLint max_ubo_bindings;
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_ubo_bindings);
printf("max uniform buffer object binding points: %d \n", max_ubo_bindings);
}
gl_buffer
initTransforms(transforms* xforms,
GLContext* gl_ctx,
float fov = DEFAULT_FOV,
float near_clip_plane = NEAR_CLIP_PLANE,
float aspect_ratio = DEFAULT_ASPECT_RATIO,
glm::vec3 cam_pos = DEFAULT_CAM_POS,
glm::vec3 look_pos = DEFAULT_LOOK_POS)
{
xforms->view_xform = glm::lookAt(cam_pos, look_pos, glm::vec3(0, 1, 0));
xforms->proj_xform = glm::infinitePerspective(
glm::radians(fov), aspect_ratio, near_clip_plane);
gl_buffer ubo = {0};
glGenBuffers(1, &ubo.id);
ubo.target = GL_UNIFORM_BUFFER;
ubo.data_type = GL_FLOAT;
ubo.data_size = sizeof(*xforms);
glBindBuffer(GL_UNIFORM_BUFFER, ubo.id);
glBufferData(GL_UNIFORM_BUFFER, sizeof(*xforms), xforms, GL_DYNAMIC_DRAW);
// NOTE: need to manually keep track of block bindings
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &gl_ctx->max_binding_points);
glBindBufferBase(GL_UNIFORM_BUFFER, gl_ctx->binding_count, ubo.id);
ubo.binding_idx = gl_ctx->binding_count;
gl_ctx->binding_count++;
glBindBuffer(GL_UNIFORM_BUFFER, 0);
return ubo;
}
mesh
initCubeMesh()
@ -224,48 +39,18 @@ initCubeMesh()
return m;
}
gl_mesh
loadGLMesh(shader_program* s,
const mesh& m,
GLenum draw_mode,
const glm::vec3& pos)
shader_program*
getShaderByName(const char* name, ShaderArray* s_arr)
{
gl_mesh gm = {0};
gm.num_indices = m.num_indices;
gm.draw_mode = draw_mode;
// NOTE: okay to store shader_program pointer on gl_mesh here because we
// won't ever delete the shader
gm.shader = s;
glUseProgram(s->prog_id);
glGenVertexArrays(1, &gm.vao_id);
glBindVertexArray(gm.vao_id);
gm.model_xform = (glm::mat4*) std::calloc(1, sizeof(glm::mat4));
*gm.model_xform = glm::translate(glm::mat4(1), pos);
glUniformMatrix4fv(
s->model_xform_id, 1, GL_FALSE, (float*) gm.model_xform);
glGenBuffers(1, &gm.vert_buf_id);
glBindBuffer(GL_ARRAY_BUFFER, gm.vert_buf_id);
glBufferData(GL_ARRAY_BUFFER,
m.num_vertices * 3 * sizeof(GLfloat),
m.vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(POSITION);
glGenBuffers(1, &gm.idx_buf_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gm.idx_buf_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
m.num_indices * sizeof(GLuint),
m.indices,
GL_STATIC_DRAW);
glBindVertexArray(0);
glUseProgram(0);
u64 hash = utilFNV64a_str(name);
for (u32 i = 0; i < s_arr->count; i++) {
if (utilFNV64a_str(s_arr->shaders[i].name) == hash)
return &s_arr->shaders[i];
}
return gm;
std::cout << "shader not found, " << name << "\n";
return nullptr;
}
shader_program*
@ -280,74 +65,42 @@ getShaderByID(ShaderArray* sarr, GLuint prog_id)
return nullptr;
}
void
loop(RenderState* rs)
// NOTE: equivalent to rgAppend() in libTangerine
model*
getModel(RenderState* rs, const char* filepath)
{
u32 delay = 60;
u32 frame_start, frame_time;
bool running = true;
SDL_Event e;
while (running) {
frame_start = SDL_GetTicks();
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT ||
(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE))
{
running = false;
break;
}
}
glClearColor(0.2, 0.2, 0.2, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
for (u32 i = 0; i < rs->gl_mesh_arr->count; i++) {
gl_mesh& glm = rs->gl_mesh_arr->gl_meshes[i];
*glm.model_xform = glm::rotate(
*glm.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0));
glUseProgram(glm.shader->prog_id);
glBindVertexArray(glm.vao_id);
glUniformMatrix4fv(glm.shader->model_xform_id, 1, GL_FALSE,
(float*) glm.model_xform);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glm.idx_buf_id);
glDrawElements(
glm.draw_mode, glm.num_indices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
model* mdl = assetGetCached(rs->assets, utilFNV64a_str(filepath));
SDL_GL_SwapWindow(g_window);
glUseProgram(0);
frame_time = SDL_GetTicks() - frame_start;
if (!mdl)
mdl = assetLoadFromFile(rs->assets, rs->textures, rs->arena, filepath);
if (delay > frame_time)
SDL_Delay(delay - frame_time);
}
return mdl;
}
void
quit(RenderState* rs)
bool
addGLMesh(gl_mesh_array* gma, gl_mesh* gm)
{
if (rs->arena)
std::free(rs->arena);
if (gma->count < gma->max) {
// FIXME: wtf was I doing here?
gma->count++;
SDL_GL_DeleteContext(g_glContext);
SDL_DestroyWindow(g_window);
SDL_Quit();
}
return false;
}
// NOTE: equivalent to rgAppend() in libTangerine
model*
getModel(RenderState* rs, const char* filepath)
gl_mesh*
getGLMesh(gl_mesh_array* gma)
{
model* mdl = assetGetCached(rs->assets, utilFNV64a_str(filepath));
if (gma->count < gma->max) {
gl_mesh* glm = &gma->gl_meshes[gma->count];
gma->count++;
if (!mdl)
mdl = assetLoadFromFile(rs->assets, rs->textures, rs->arena, filepath);
return glm;
}
return mdl;
std::cout << "Error, gl_mesh_array is full\n";
return nullptr;
}
ShaderArray*
@ -401,130 +154,82 @@ initRenderState(memory_arena* arena)
rs->gl_ctx = initGLContext(arena);
rs->xforms =
(transforms*) arenaAllocateBlock(arena, sizeof(transforms));
rs->handles =
(SDLHandles*) arenaAllocateBlock(arena, sizeof(SDLHandles));
rs->gl_mesh_arr = initGLMeshArray(arena, 256);
}
return rs;
}
// TODO: clean up this function
void
openglDebugCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam)
{
std::cout << ((type == GL_DEBUG_TYPE_ERROR) ? "Error" : "Debug")
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "")
<< ", type: " << type
<< ", severity: " << severity
<< ", message: " << message << "\n";
}
bool
addShaderProgram(memory_arena* arena,
GLContext* gl_ctx,
const char* vs,
const char* fs,
const char* name)
initGraphics(SDLHandles* handles)
{
if (gl_ctx->shader_arr->count >= gl_ctx->shader_arr->max) {
std::cout << "ShaderArray full\n";
handles->window = SDL_CreateWindow(
"shader_testing",
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
1280,
720,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "error, sdl init: " << SDL_GetError() << "\n";
return false;
}
shader_program* s = &gl_ctx->shader_arr->shaders[gl_ctx->shader_arr->count];
gl_ctx->shader_arr->count++;
u32 name_len = std::strlen(name) + 1;
s->name = (char*) arenaAllocateBlock(arena, name_len);
std::strncpy(s->name, name, name_len);
const u32 max_len = 256;
std::string hash_str = vs;
hash_str += fs;
s->hash = utilFNV64a_str(hash_str.substr(0, max_len).c_str());
// FIXME: should probably check the hash here against other shaders loaded
std::string vert = dumpTextFile(vs);
std::string frag = dumpTextFile(fs);
if (vert.size() > 0 && frag.size() > 0) {
const char* vert_c = vert.c_str();
const char* frag_c = frag.c_str();
GLuint vs_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fs_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs_id, 1, &vert_c, NULL);
glShaderSource(fs_id, 1, &frag_c, NULL);
// TODO: both of these can fail
glCompileShader(vs_id);
glCompileShader(fs_id);
s->prog_id = glCreateProgram();
glAttachShader(s->prog_id, vs_id);
glAttachShader(s->prog_id, fs_id);
glLinkProgram(s->prog_id);
GLint is_linked = 0;
glGetProgramiv(s->prog_id, GL_LINK_STATUS, &is_linked);
if (is_linked) {
s->model_xform_id = glGetUniformLocation(s->prog_id, "model_xform");
// FIXME: testing
// NOTE: set block binding for shader xforms uniform block
GLuint block_idx = glGetUniformBlockIndex(s->prog_id, "matrices");
glUniformBlockBinding(s->prog_id,
block_idx,
gl_ctx->xform_ubo.binding_idx);
// FIXME: fill out new shader extra uniforms and buffers here
dumpShader(s->prog_id);
printf("offset of RenderState.xforms: %lu bytes\n",
offsetof(RenderState, xforms));
parseShaderUniforms(arena, s, gl_ctx);
///
glDetachShader(s->prog_id, vs_id);
glDetachShader(s->prog_id, fs_id);
glDeleteShader(vs_id);
glDeleteShader(fs_id);
SDL_GL_SetSwapInterval(1);
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->display_mode);
return true;
}
handles->sdl_gl_ctx = SDL_GL_CreateContext(handles->window);
printf("%s(), Error linking shader\n", __FUNCTION__);
if (!handles->sdl_gl_ctx) {
std::cout << "error creating context\n";
return false;
}
if (glewInit()) {
std::cout << "error initializing opengl\n";
return false;
}
bool
addGLMesh(gl_mesh_array* gma, gl_mesh* gm)
{
if (gma->count < gma->max) {
// FIXME: wtf was I doing here?
gma->count++;
}
return false;
}
shader_program*
getShaderByName(const char* name, ShaderArray* s_arr)
{
u64 hash = utilFNV64a_str(name);
for (u32 i = 0; i < s_arr->count; i++) {
if (utilFNV64a_str(s_arr->shaders[i].name) == hash)
return &s_arr->shaders[i];
}
std::cout << "shader not found, " << name << "\n";
return nullptr;
}
std::cout << "opengl vendor: " << glGetString(GL_VENDOR) << "\n";
std::cout << "opengl renderer: " << glGetString(GL_RENDERER) << "\n";
std::cout << "opengl version: " << glGetString(GL_VERSION) << "\n";
gl_mesh*
getGLMesh(gl_mesh_array* gma)
{
if (gma->count < gma->max) {
gl_mesh* glm = &gma->gl_meshes[gma->count];
gma->count++;
glEnable(GL_DEPTH_TEST);
glEnable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
return glm;
}
glEnable (GL_DEBUG_OUTPUT);
glDebugMessageCallback((GLDEBUGPROC) openglDebugCallback, 0);
std::cout << "Error, gl_mesh_array is full\n";
return nullptr;
return handles->window != nullptr;
}
bool
@ -563,15 +268,63 @@ loadScene(RenderState* rs)
return true;
}
void
loop(RenderState* rs)
{
u32 delay = 60;
u32 frame_start, frame_time;
bool running = true;
SDL_Event e;
while (running) {
frame_start = SDL_GetTicks();
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT ||
(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE))
{
running = false;
break;
}
}
glClearColor(0.2, 0.2, 0.2, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
for (u32 i = 0; i < rs->gl_mesh_arr->count; i++) {
gl_mesh& glm = rs->gl_mesh_arr->gl_meshes[i];
*glm.model_xform = glm::rotate(
*glm.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0));
renderVAO(&glm);
}
SDL_GL_SwapWindow(rs->handles->window);
glUseProgram(0);
frame_time = SDL_GetTicks() - frame_start;
if (delay > frame_time)
SDL_Delay(delay - frame_time);
}
}
void
quit(RenderState* rs)
{
SDL_GL_DeleteContext(rs->handles->sdl_gl_ctx);
SDL_DestroyWindow(rs->handles->window);
SDL_Quit();
std::free(rs->arena);
}
int
main()
{
if (!initGraphics())
return 1;
memory_arena* arena = arenaInit(DEFAULT_ARENA_SIZE);
RenderState* rs = initRenderState(arena);
if (!initGraphics(rs->handles))
return 1;
if (rs) {
rs->gl_ctx->xform_ubo = initTransforms(rs->xforms, rs->gl_ctx);

262
src/shader.cpp

@ -0,0 +1,262 @@
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <string>
#include <fstream>
#include <iostream>
#include <glm/gtc/matrix_transform.hpp>
#include "asset.h"
#include "shader.h"
#include "dumpShader.inl"
// NOTE: forward declarations
const std::string dumpTextFile(const char* filepath);
void
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx);
// NOTE: interface
// TODO: clean up this function
bool
addShaderProgram(memory_arena* arena,
GLContext* gl_ctx,
const char* vs,
const char* fs,
const char* name)
{
if (gl_ctx->shader_arr->count >= gl_ctx->shader_arr->max) {
std::cout << "ShaderArray full\n";
return false;
}
shader_program* s = &gl_ctx->shader_arr->shaders[gl_ctx->shader_arr->count];
gl_ctx->shader_arr->count++;
u32 name_len = std::strlen(name) + 1;
s->name = (char*) arenaAllocateBlock(arena, name_len);
std::strncpy(s->name, name, name_len);
const u32 max_len = 256;
std::string hash_str = vs;
hash_str += fs;
s->hash = utilFNV64a_str(hash_str.substr(0, max_len).c_str());
// FIXME: should probably check the hash here against other shaders loaded
std::string vert = dumpTextFile(vs);
std::string frag = dumpTextFile(fs);
if (vert.size() > 0 && frag.size() > 0) {
const char* vert_c = vert.c_str();
const char* frag_c = frag.c_str();
GLuint vs_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fs_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs_id, 1, &vert_c, NULL);
glShaderSource(fs_id, 1, &frag_c, NULL);
// TODO: both of these can fail
glCompileShader(vs_id);
glCompileShader(fs_id);
s->prog_id = glCreateProgram();
glAttachShader(s->prog_id, vs_id);
glAttachShader(s->prog_id, fs_id);
glLinkProgram(s->prog_id);
GLint is_linked = 0;
glGetProgramiv(s->prog_id, GL_LINK_STATUS, &is_linked);
if (is_linked) {
s->model_xform_id = glGetUniformLocation(s->prog_id, "model_xform");
// FIXME: testing
// NOTE: set block binding for shader xforms uniform block
GLuint block_idx = glGetUniformBlockIndex(s->prog_id, "matrices");
glUniformBlockBinding(s->prog_id,
block_idx,
gl_ctx->xform_ubo.binding_idx);
// FIXME: fill out new shader extra uniforms and buffers here
dumpShader(s->prog_id);
printf("offset of RenderState.xforms: %lu bytes\n",
offsetof(RenderState, xforms));
parseShaderUniforms(arena, s, gl_ctx);
///
glDetachShader(s->prog_id, vs_id);
glDetachShader(s->prog_id, fs_id);
glDeleteShader(vs_id);
glDeleteShader(fs_id);
return true;
}
printf("%s(), Error linking shader\n", __FUNCTION__);
return false;
}
return false;
}
void
renderVAO(gl_mesh* glmesh)
{
glUseProgram(glmesh->shader->prog_id);
glBindVertexArray(glmesh->vao_id);
glUniformMatrix4fv(glmesh->shader->model_xform_id, 1, GL_FALSE,
(float*) glmesh->model_xform);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glmesh->idx_buf_id);
glDrawElements(
glmesh->draw_mode, glmesh->num_indices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
// NOTE: internal
const std::string
dumpTextFile(const char* filepath)
{
std::ifstream fs { filepath };
std::string s {
std::istreambuf_iterator<char>(fs),
std::istreambuf_iterator<char>()};
if (!fs || !fs.good())
std::cout << "error reading file, " << filepath << "\n";
return s;
}
void
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx)
{
GLint unif_count;
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORMS, &unif_count);
s->num_uniforms = unif_count;
s->uniforms = (gl_uniform*) arenaAllocateBlock(
arena, s->num_uniforms * sizeof(gl_uniform));
for (u32 i = 0; i < s->num_uniforms; i++) {
GLchar unif_name[256] = {0};
GLsizei length;
GLint size;
GLenum type;
glGetActiveUniform(s->prog_id, i, sizeof(unif_name),
&length, &size, &type, unif_name);
s->uniforms[i].data_type = type;
s->uniforms[i].name = (char*) arenaAllocateBlock(
arena, (length + 1) * sizeof(char));
std::strncpy(s->uniforms[i].name, unif_name, length);
glGetActiveUniformsiv(s->prog_id, 1, &i,
GL_UNIFORM_BLOCK_INDEX, &s->uniforms[i].block_idx);
// FIXME: testing idx == unif location
s->uniforms[i].idx = i;
GLuint location = glGetUniformLocation(s->prog_id, s->uniforms[i].name);
printf("idx: %d, loc: %d, block idx: %d \n",
i, location, s->uniforms[i].block_idx);
// TODO: get uniform.data_size from data_type
//printf("i: %d, uniform name: %s, l: %d \n", i, unif_name, length);
}
GLint max_vert_ublocks;
GLint max_frag_ublocks;
GLint max_ublock_size;
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &max_vert_ublocks);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &max_frag_ublocks);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ublock_size);
printf("max vert uniform blocks: %d, max frag uniform blocks: %d,"
"max uniform block size: %d bytes \n",
max_vert_ublocks, max_frag_ublocks, max_ublock_size);
GLint max_ubo_bindings;
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_ubo_bindings);
printf("max uniform buffer object binding points: %d \n", max_ubo_bindings);
}
gl_buffer
initTransforms(transforms* xforms,
GLContext* gl_ctx,
float fov,
float near_clip_plane,
float aspect_ratio,
glm::vec3 cam_pos,
glm::vec3 look_pos)
{
xforms->view_xform = glm::lookAt(cam_pos, look_pos, glm::vec3(0, 1, 0));
xforms->proj_xform = glm::infinitePerspective(
glm::radians(fov), aspect_ratio, near_clip_plane);
gl_buffer ubo = {0};
glGenBuffers(1, &ubo.id);
ubo.target = GL_UNIFORM_BUFFER;
ubo.data_type = GL_FLOAT;
ubo.data_size = sizeof(*xforms);
glBindBuffer(GL_UNIFORM_BUFFER, ubo.id);
glBufferData(GL_UNIFORM_BUFFER, sizeof(*xforms), xforms, GL_DYNAMIC_DRAW);
// NOTE: need to manually keep track of block bindings
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &gl_ctx->max_binding_points);
glBindBufferBase(GL_UNIFORM_BUFFER, gl_ctx->binding_count, ubo.id);
ubo.binding_idx = gl_ctx->binding_count;
gl_ctx->binding_count++;
glBindBuffer(GL_UNIFORM_BUFFER, 0);
return ubo;
}
gl_mesh
loadGLMesh(shader_program* s,
const mesh& m,
GLenum draw_mode,
const glm::vec3& pos)
{
gl_mesh gm = {0};
gm.num_indices = m.num_indices;
gm.draw_mode = draw_mode;
// NOTE: okay to store shader_program pointer on gl_mesh here because we
// won't ever delete the shader
gm.shader = s;
glUseProgram(s->prog_id);
glGenVertexArrays(1, &gm.vao_id);
glBindVertexArray(gm.vao_id);
gm.model_xform = (glm::mat4*) std::calloc(1, sizeof(glm::mat4));
*gm.model_xform = glm::translate(glm::mat4(1), pos);
glUniformMatrix4fv(
s->model_xform_id, 1, GL_FALSE, (float*) gm.model_xform);
glGenBuffers(1, &gm.vert_buf_id);
glBindBuffer(GL_ARRAY_BUFFER, gm.vert_buf_id);
glBufferData(GL_ARRAY_BUFFER,
m.num_vertices * 3 * sizeof(GLfloat),
m.vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(POSITION);
glGenBuffers(1, &gm.idx_buf_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gm.idx_buf_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
m.num_indices * sizeof(GLuint),
m.indices,
GL_STATIC_DRAW);
glBindVertexArray(0);
glUseProgram(0);
return gm;
}

35
src/shader_testing.h → src/shader.h

@ -1,6 +1,7 @@
#pragma once
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <glm/glm.hpp>
@ -115,6 +116,13 @@ struct light_array
point_light* lights;
};
struct SDLHandles
{
SDL_Window* window;
SDL_GLContext sdl_gl_ctx;
SDL_DisplayMode display_mode;
};
struct RenderState
{
memory_arena* arena;
@ -122,6 +130,7 @@ struct RenderState
texture_assets* textures;
transforms* xforms; // NOTE: would be part of camera in libTangerine
SDLHandles* handles;
GLContext* gl_ctx;
gl_mesh_array* gl_mesh_arr;
@ -132,3 +141,29 @@ struct node;
struct entity;
struct animation;
const float DEFAULT_FOV = 60.f;
const float NEAR_CLIP_PLANE = 5.f;
const float DEFAULT_ASPECT_RATIO = 16.f / 9.f;
const glm::vec3 DEFAULT_CAM_POS = { 0, 0, -30.f };
const glm::vec3 DEFAULT_LOOK_POS = { 0, 0, 0 };
bool addShaderProgram(memory_arena* arena,
GLContext* gl_ctx,
const char* vs,
const char* fs,
const char* name);
void renderVAO(gl_mesh* glmesh);
gl_mesh loadGLMesh(shader_program* s,
const mesh& m,
GLenum draw_mode,
const glm::vec3& pos);
gl_buffer initTransforms(transforms* xforms,
GLContext* gl_ctx,
float fov = DEFAULT_FOV,
float near_clip_plane = NEAR_CLIP_PLANE,
float aspect_ratio = DEFAULT_ASPECT_RATIO,
glm::vec3 cam_pos = DEFAULT_CAM_POS,
glm::vec3 look_pos = DEFAULT_LOOK_POS);
Loading…
Cancel
Save