Browse Source

Initial commit

new file:   .gitignore
	new file:   Makefile
	new file:   dumpShader.inl
	new file:   main.cpp
	new file:   shader_testing
	new file:   shader_testing.h
main
cinnaboot 5 years ago
commit
3afa3d9cc8
  1. 7
      .gitignore
  2. 15
      Makefile
  3. 61
      dumpShader.inl
  4. 349
      main.cpp
  5. BIN
      shader_testing
  6. 96
      shader_testing.h

7
.gitignore vendored

@ -0,0 +1,7 @@
tags
*.d
*.bin
data/
build/

15
Makefile

@ -0,0 +1,15 @@
SHELL = /bin/sh
CXX = g++
CXXFLAGS = -std=c++11 -g -ggdb3 -Wall -I/usr/include/SDL2
LDFLAGS = -lSDL2 -lGLEW -lGL
BIN = shader_testing
all:
$(CXX) $(CXXFLAGS) -MMD main.cpp -o $(BIN) $(LDFLAGS)
.PHONY: all
clean:
rm -rf $(BIN)
.PHONY: clean

61
dumpShader.inl

@ -0,0 +1,61 @@
#include <GL/glew.h>
#include "shader_testing.h"
const char* gl_enum_to_string(GLenum e);
void
dumpShader(GLuint prog_id)
{
std::cout << "dumping shader info, program id: " << prog_id << "\n";
GLint active_uniforms;
GLint active_uniform_blocks;
GLint active_attribs;
// NOTE: unused uniforms/attributes get optimized away
// https://www.khronos.org/opengl/wiki/Program_Introspection#Attributes
// https://stackoverflow.com/questions/54811319/how-to-get-from-glgetattriblocation-to-glgetactiveattrib-index
glGetProgramiv(prog_id, GL_ACTIVE_UNIFORMS, &active_uniforms);
glGetProgramiv(prog_id, GL_ACTIVE_UNIFORM_BLOCKS, &active_uniform_blocks);
glGetProgramiv(prog_id, GL_ACTIVE_ATTRIBUTES, &active_attribs);
printf("active uniforms: %d\n", active_uniforms);
printf("active uniform blocks: %d\n", active_uniform_blocks);
printf("active attributes: %d\n", active_attribs);
GLchar uni_name[256];
GLsizei length;
GLint size;
GLenum type;
for (int i = 0; i < active_uniforms; i++) {
glGetActiveUniform(prog_id, i, sizeof(uni_name),
&length, &size, &type, uni_name);
printf("uniform idx: %d, len: %d, type: %s, name: %s \n",
i, length, gl_enum_to_string(type), uni_name);
}
for (int i = 0; i < active_attribs; i++) {
glGetActiveAttrib(prog_id, i, sizeof(uni_name),
&length, &size, &type, uni_name);
printf("attribute idx: %d, len: %d, type: %s, name: %s \n",
i, length, gl_enum_to_string(type), uni_name);
}
}
const char*
gl_enum_to_string(GLenum e)
{
switch (e) {
case 0x8b5c: return "GL_FLOAT_MAT4";
case 0x8b51: return "GL_FLOAT_VEC3";
default: return "???";
}
}

349
main.cpp

@ -0,0 +1,349 @@
#include <cassert>
#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 "shader_testing.h"
#include "dumpShader.inl"
SDL_Window *g_window = 0;
SDL_GLContext g_glContext;
SDL_DisplayMode g_display_mode;
transforms g_xforms;
mesh g_cube_mesh;
const u32 NUM_CUBES = 4;
gl_mesh g_gl_cubes[NUM_CUBES];
glm::vec3 g_cube_locs[NUM_CUBES] = {
glm::vec3(-10, 10, 0),
glm::vec3(-10, -10, 0),
glm::vec3( 10, 10, 0),
glm::vec3( 10, -10, 0),
};
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
init()
{
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;
}
bool
loadShaderProgram(const char* vs, const char* fs, shader* s)
{
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);
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);
glDetachShader(s->prog_id, vs_id);
glDetachShader(s->prog_id, fs_id);
glDeleteShader(vs_id);
glDeleteShader(fs_id);
GLint is_linked = 0;
glGetProgramiv(s->prog_id, GL_LINK_STATUS, &is_linked);
return (is_linked == GL_TRUE);
}
return false;
}
transforms
initXformUBO(shader* s,
float fov,
float near_clip_plane,
float aspect_ratio,
glm::vec3 cam_pos,
glm::vec3 look_pos)
{
transforms xforms;
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);
xforms.normal_xform = glm::mat4(1);
glGenBuffers(1, &s->xforms_ubo_id);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, s->xforms_ubo_id);
glBindBuffer(GL_UNIFORM_BUFFER, s->xforms_ubo_id);
glBufferData(GL_UNIFORM_BUFFER, sizeof(xforms), &xforms, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
return xforms;
};
mesh
initCubeMesh()
{
mesh m = {0};
m.num_vertices = 8;
m.vertices = (glm::vec3*) std::calloc(m.num_vertices, sizeof(glm::vec3));
m.vertices[0] = { -1, 1, -1 };
m.vertices[1] = { -1, -1, -1 };
m.vertices[2] = { 1, -1, -1 };
m.vertices[3] = { 1, 1, -1 };
m.vertices[4] = { -1, 1, 1 };
m.vertices[5] = { -1, -1, 1 };
m.vertices[6] = { 1, -1, 1 };
m.vertices[7] = { 1, 1, 1 };
m.num_indices = 36; // 6 sides, 2 tris per side, 3 verts per tri
m.indices = (u32*) std::calloc(m.num_indices, sizeof(u32));
u32 indices[36] = {
0, 1, 2, 0, 2, 3,
3, 2, 6, 3, 6, 7,
7, 6, 5, 7, 5, 4,
4, 5, 0, 4, 1, 0,
0, 3, 4, 0, 3, 7,
1, 2, 5, 2, 6, 5
};
std::memcpy(m.indices, indices, m.num_indices * sizeof(u32));
return m;
}
gl_mesh
loadGLMesh(shader* 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;
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);
gm.model_xform_id = glGetUniformLocation(s->prog_id, "model_xform");
glUniformMatrix4fv(
gm.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;
}
void
loop(shader* s, gl_mesh* mesh_arr, u32 num_meshes)
{
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);
glUseProgram(s->prog_id);
glBindBuffer(GL_UNIFORM_BUFFER, s->xforms_ubo_id);
for (u32 i = 0; i < num_meshes; i++) {
const gl_mesh& m = mesh_arr[i];
*m.model_xform = glm::rotate(
*m.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0));
glBindVertexArray(m.vao_id);
glUniformMatrix4fv(
m.model_xform_id, 1, GL_FALSE, (float*) m.model_xform);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m.idx_buf_id);
glDrawElements(m.draw_mode, m.num_indices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
SDL_GL_SwapWindow(g_window);
glUseProgram(0);
frame_time = SDL_GetTicks() - frame_start;
if (delay > frame_time)
SDL_Delay(delay - frame_time);
}
}
void
quit(shader* s)
{
glDeleteProgram(s->prog_id);
SDL_GL_DeleteContext(g_glContext);
SDL_DestroyWindow(g_window);
SDL_Quit();
for (u32 i = 0; i < NUM_CUBES; i++) {
gl_mesh& c = g_gl_cubes[i];
if (c.model_xform != nullptr)
free(c.model_xform);
}
mesh& cm = g_cube_mesh;
if (cm.vertices != nullptr)
free(cm.vertices);
if (cm.normals != nullptr)
free(cm.normals);
if (cm.uvs != nullptr)
free(cm.uvs);
if (cm.colors != nullptr)
free(cm.colors);
if (cm.indices != nullptr)
free(cm.indices);
}
int
main()
{
if (!init())
return 1;
shader s = {0};
if (loadShaderProgram("data/shader.vert", "data/shader.frag", &s)) {
dumpShader(s.prog_id);
g_xforms = initXformUBO(&s);
g_cube_mesh = initCubeMesh();
for (u32 i = 0; i < NUM_CUBES; i++) {
g_gl_cubes[i] =
loadGLMesh(&s, g_cube_mesh, GL_TRIANGLES, g_cube_locs[i]);
assert(g_gl_cubes[i].vao_id != 0);
}
loop(&s, g_gl_cubes, NUM_CUBES);
quit(&s);
return 0;
}
std::cout << "error loading shader program\n";
quit(&s);
return 1;
}

BIN
shader_testing

Binary file not shown.

96
shader_testing.h

@ -0,0 +1,96 @@
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
typedef uint32_t u32;
struct gl_uniform
{
GLenum id;
GLenum data_type;
};
struct gl_buffer
{
GLuint id;
GLenum data_type;
};
struct shader
{
GLuint prog_id;
GLuint xforms_ubo_id;
};
struct transforms
{
glm::mat4 view_xform;
glm::mat4 proj_xform;
glm::mat4 normal_xform;
};
enum glsl_layout
{
POSITION,
NORMAL,
UV,
COLOR
};
struct mesh
{
u32 num_vertices;
u32 num_indices;
glm::vec3* vertices;
glm::vec3* normals;
glm::vec3* uvs;
glm::vec3* colors;
u32* indices;
};
struct gl_mesh
{
u32 num_indices;
GLuint vao_id;
GLuint tex_id;
GLenum draw_mode;
glm::mat4* model_xform;
GLuint model_xform_id;
GLuint vert_buf_id;
GLuint norm_buf_id;
GLuint uv_buf_id;
GLuint clr_buf_id;
GLuint idx_buf_id;
};
struct node;
struct entity;
struct light;
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 loadShaderProgram(const char* vs, const char* fs, shader* s);
transforms initXformUBO(shader* s,
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);
mesh initCubeMesh();
gl_mesh loadGLMesh(shader* s, const mesh& m, const glm::vec3& pos);
void loop(shader* s, gl_mesh* mesh_arr, u32 num_meshes);
void quit(shader* s);
Loading…
Cancel
Save