commit 81153bdbc220710adfac845d2491462e914d175c
parent 92d6d25eff4b7dd560d03b3b79a10be05df1260c
Author: David DiPaola <DavidDiPaola@users.noreply.github.com>
Date: Tue, 22 May 2018 06:10:16 -0400
initial commit
Diffstat:
10 files changed, 368 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+00-triangle
+
+.*.swp
+
diff --git a/00-triangle.c b/00-triangle.c
@@ -0,0 +1,96 @@
+#include <stdio.h>
+
+#include <stdlib.h>
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+#include "ogl/ogl.h"
+
+int
+main() {
+ int status;
+
+ GLFWwindow * window = NULL;
+ status = ogl_init(400, 240, "00 - triangle", &window);
+ if (status < 0) {
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return status;
+ }
+
+ const char * vertexshader =
+ "#version 100" "\n"
+ "attribute vec4 position;" "\n"
+ "void main(){" "\n"
+ " gl_Position = position;" "\n"
+ "}" "\n"
+ ;
+ const char * fragmentshader =
+ "#version 100" "\n"
+ "void main() {" "\n"
+ " gl_FragColor = vec4(1,0,0,1);" "\n"
+ "}" "\n"
+ ;
+ GLuint program_ID = 0;
+ status = ogl_program_build(
+ vertexshader, fragmentshader,
+ &program_ID
+ );
+ if (status < 0) {
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return status;
+ }
+
+ GLint program_attribute_position_ID = 0;
+ status = ogl_program_attribute_get_ID(program_ID, "position", &program_attribute_position_ID);
+ if (status < 0) {
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return status;
+ }
+
+ static const GLfloat triangle_vertex_data[] = {
+ -1.0f, -1.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ };
+ GLuint triangle_vertex_buffer_ID = 0;
+ status = ogl_vertex_buffer_load(triangle_vertex_data, sizeof(triangle_vertex_data), &triangle_vertex_buffer_ID);
+ if (status < 0) {
+ return status;
+ }
+
+ do {
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUseProgram(program_ID);
+
+ glEnableVertexAttribArray(program_attribute_position_ID);
+ glBindBuffer(GL_ARRAY_BUFFER, triangle_vertex_buffer_ID);
+ glVertexAttribPointer(
+ program_attribute_position_ID, // The attribute we want to configure
+ 3, // size
+ GL_FLOAT, // type
+ GL_FALSE, // is normalized?
+ 0, // stride
+ (GLvoid *)0 // array buffer offset
+ );
+ glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDisableVertexAttribArray(triangle_vertex_buffer_ID);
+
+ glfwSwapBuffers(window);
+ glfwPollEvents();
+ }
+ while (
+ (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS)
+ &&
+ (glfwWindowShouldClose(window) == 0)
+ );
+
+ glDeleteBuffers(1, &triangle_vertex_buffer_ID);
+ glDeleteProgram(program_ID);
+
+ glfwTerminate();
+
+ return 0;
+}
+
diff --git a/Makefile b/Makefile
@@ -0,0 +1,28 @@
+SRC = \
+ 00-triangle.c \
+ ogl/_ogl.c ogl/ogl_init.c ogl/ogl_program_build.c ogl/ogl_program_attribute_get_ID.c ogl/ogl_vertex_buffer_load.c
+LIB = glew gl glfw3
+BIN = 00-triangle
+
+OBJ = $(SRC:.c=.o)
+
+CFLAGS ?= -std=c99 -Wall -fwrapv -g
+LIB_CFLAGS += $(shell pkg-config --cflags glew gl glfw3)
+LIB_LDFLAGS += $(shell pkg-config --libs glew gl glfw3)
+
+.PHONY: all
+all: $(BIN)
+
+.PHONY: clean
+clean:
+ @echo [RM] $(OBJ) $(BIN)
+ @rm -rf $(OBJ) $(BIN)
+
+%.o: %.c
+ @echo [CC] $<
+ @$(CC) $(CFLAGS) $(LIB_CFLAGS) -c $< -o $@
+
+$(BIN): $(OBJ)
+ @echo [LD] $^ -o $@
+ @$(CC) $(LDFLAGS) $^ -o $@ $(LIB_LDFLAGS)
+
diff --git a/ogl/_ogl.c b/ogl/_ogl.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int _ogl_window_width = 0;
+int _ogl_window_height = 0;
+
+void
+_ogl_glfw_error(int error, const char * description) {
+ fprintf(stderr, "GLFW ERROR: (%i) %s" "\n", error, description);
+}
+
diff --git a/ogl/_ogl.h b/ogl/_ogl.h
@@ -0,0 +1,6 @@
+extern int _ogl_window_width;
+extern int _ogl_window_height;
+
+void
+_ogl_glfw_error(int error, const char * description);
+
diff --git a/ogl/ogl.h b/ogl/ogl.h
@@ -0,0 +1,24 @@
+int
+ogl_init(
+ int window_width, int window_height, const char * window_title,
+ GLFWwindow ** out_window
+);
+
+int
+ogl_program_build(
+ const char * vertexshader, const char * fragmentshader,
+ GLuint * out_program_ID
+);
+
+int
+ogl_program_attribute_get_ID(
+ GLuint programID, const char * attribute_name,
+ GLint * out_attribute_ID
+);
+
+int
+ogl_vertex_buffer_load(
+ const GLvoid * data, GLsizeiptr data_size,
+ GLuint * out_bufferID
+);
+
diff --git a/ogl/ogl_init.c b/ogl/ogl_init.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+
+#include <GL/glew.h>
+
+#include <GLFW/glfw3.h>
+
+#include "ogl.h"
+#include "_ogl.h"
+
+int
+ogl_init(
+ int window_width, int window_height, const char * window_title,
+ GLFWwindow ** out_window
+) {
+ GLFWwindow * window;
+ int status;
+
+ glfwSetErrorCallback(&_ogl_glfw_error);
+
+ status = glfwInit();
+ if (!status) { /* TODO GLFW_TRUE doesn't exist..? */
+ fprintf(stderr, "GLFW glfwInit(): ERROR" "\n");
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+
+ window = glfwCreateWindow(window_width, window_height, window_title, NULL, NULL);
+ if (window == NULL){
+ fprintf(stderr, "GLFW glfwCreateWindow(): ERROR" "\n");
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ glfwTerminate();
+ return -1;
+ }
+ _ogl_window_width = window_width;
+ _ogl_window_height = window_height;
+
+ glfwMakeContextCurrent(window);
+
+ GLenum glewstatus;
+ glewstatus = glewInit();
+ if (glewstatus != GLEW_OK) {
+ fprintf(stderr, "GLEW glewInit(): ERROR" "\n");
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ glfwTerminate();
+ return -1;
+ }
+
+ glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
+
+ glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
+
+ (*out_window) = window;
+ return 0;
+}
+
diff --git a/ogl/ogl_program_attribute_get_ID.c b/ogl/ogl_program_attribute_get_ID.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+#include <GL/glew.h>
+
+int
+ogl_program_attribute_get_ID(
+ GLuint program_ID, const char * attribute_name,
+ GLint * out_attribute_ID
+) {
+ GLint attribute_ID;
+
+ attribute_ID = glGetAttribLocation(program_ID, attribute_name);
+ if (attribute_ID < 0) {
+ fprintf(stderr, "GL glGetAttribLocation(%i, \"%s\"): ERROR" "\n", program_ID, attribute_name);
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ (*out_attribute_ID) = attribute_ID;
+ return 0;
+}
+
diff --git a/ogl/ogl_program_build.c b/ogl/ogl_program_build.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+
+#include <stdlib.h>
+
+#include <GL/glew.h>
+
+#include <GLFW/glfw3.h>
+
+static int
+_shader_compile(
+ GLenum shader_type, const char * shader_code,
+ GLuint * out_shader_ID
+) {
+ GLuint shader_ID;
+ const char * shader_type_str = (shader_type == GL_VERTEX_SHADER) ? "vertex" : "fragment";
+
+ shader_ID = glCreateShader(shader_type);
+
+ glShaderSource(shader_ID, 1, &shader_code, NULL);
+
+ glCompileShader(shader_ID);
+ GLsizei log_length = 0;
+ glGetShaderiv(shader_ID, GL_INFO_LOG_LENGTH, &log_length);
+ if (log_length > 0) {
+ GLchar * log = calloc(log_length, sizeof(GLchar)); /* TODO handle error */
+ glGetShaderInfoLog(shader_ID, log_length, NULL, log);
+ fprintf(stderr, "GL %s shader compiler: %s" "\n", shader_type_str, log);
+ free(log);
+ }
+
+ GLint status_compile = GL_FALSE;
+ glGetShaderiv(shader_ID, GL_COMPILE_STATUS, &status_compile);
+ if (status_compile != GL_TRUE) {
+ fprintf(stderr, "GL %s shader compiler: ERROR" "\n", shader_type_str);
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ (*out_shader_ID) = shader_ID;
+ return 0;
+}
+
+int
+ogl_program_build(
+ const char * vertexshader, const char * fragmentshader,
+ GLuint * out_program_ID
+) {
+ /*
+ GLenum status;
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "GL ERROR: foo() failed (GLenum %i)" "\n", status);
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ }
+ */
+ int status;
+
+ GLuint vertexshader_ID;
+ status = _shader_compile(GL_VERTEX_SHADER, vertexshader, &vertexshader_ID);
+ if (status < 0) {
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ GLuint fragmentshader_ID;
+ status = _shader_compile(GL_FRAGMENT_SHADER, fragmentshader, &fragmentshader_ID);
+ if (status < 0) {
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ GLuint program_ID = glCreateProgram();
+ glAttachShader(program_ID, vertexshader_ID);
+ glAttachShader(program_ID, fragmentshader_ID);
+ glLinkProgram(program_ID);
+ GLsizei log_length = 0;
+ glGetProgramiv(program_ID, GL_INFO_LOG_LENGTH, &log_length);
+ if ( log_length > 0 ){
+ GLchar * log = calloc(log_length, sizeof(GLchar)); /* TODO handle error */
+ glGetProgramInfoLog(program_ID, log_length, NULL, log);
+ fprintf(stderr, "GL shader program linker: %s" "\n", log);
+ free(log);
+ }
+ GLint status_compile = GL_FALSE;
+ glGetProgramiv(program_ID, GL_LINK_STATUS, &status_compile);
+ if (status_compile != GL_TRUE) {
+ fprintf(stderr, "GL shader program linker: ERROR" "\n");
+ fprintf(stderr, "\t" "at %s : %d" "\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ glDetachShader(program_ID, vertexshader_ID);
+ glDetachShader(program_ID, fragmentshader_ID);
+
+ glDeleteShader(vertexshader_ID);
+ glDeleteShader(fragmentshader_ID);
+
+ (*out_program_ID) = program_ID;
+ return 0;
+}
+
diff --git a/ogl/ogl_vertex_buffer_load.c b/ogl/ogl_vertex_buffer_load.c
@@ -0,0 +1,17 @@
+#include <GL/glew.h>
+
+int
+ogl_vertex_buffer_load(
+ const GLvoid * data, GLsizeiptr data_size,
+ GLuint * out_buffer_ID
+) {
+ GLuint buffer_ID;
+ glGenBuffers(1, &buffer_ID);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer_ID);
+ glBufferData(GL_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ (*out_buffer_ID) = buffer_ID;
+ return 0;
+}
+