From 58f136c245ceb048e4dfb807cc57fb2cdf825fc4 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 18 Oct 2025 14:19:27 -0500 Subject: [PATCH] add texture_cube/texture_cube_depth --- src/texture_cube.c | 347 ++++++++++++++++++++++++++++++++++++++ src/texture_cube.fp.glsl | 8 + src/texture_cube.vp.glsl | 10 ++ src/texture_cube_depth.c | 353 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 718 insertions(+) create mode 100644 src/texture_cube.c create mode 100644 src/texture_cube.fp.glsl create mode 100644 src/texture_cube.vp.glsl create mode 100644 src/texture_cube_depth.c diff --git a/src/texture_cube.c b/src/texture_cube.c new file mode 100644 index 0000000..e4032c4 --- /dev/null +++ b/src/texture_cube.c @@ -0,0 +1,347 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void * read_file(const char * filename) +{ + int fd = open(filename, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "open(%s): %s\n", filename, strerror(errno)); + return NULL; + } + + off_t size = lseek(fd, 0, SEEK_END); + if (size == (off_t)-1) { + fprintf(stderr, "lseek(%s, SEEK_END): %s\n", filename, strerror(errno)); + return NULL; + } + + off_t start = lseek(fd, 0, SEEK_SET); + if (start == (off_t)-1) { + fprintf(stderr, "lseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); + return NULL; + } + + void * buf = malloc(size+1); + + ssize_t read_size = read(fd, buf, size); + if (read_size == -1) { + fprintf(stderr, "read(%s): %s\n", filename, strerror(errno)); + return NULL; + } + ((char*)buf)[read_size] = 0; + + return buf; +} + +void framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +unsigned int compile_shaders() +{ + void * vertexShaderSource = read_file("src/texture_cube.vp.glsl"); + unsigned int vertexShader; + vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, (const char **)&vertexShaderSource, NULL); + glCompileShader(vertexShader); + { + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if(!success) { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + printf("vertex shader compile failed:\n%s\n", infoLog); + } + } + free(vertexShaderSource); + + void * fragmentShaderSource = read_file("src/texture_cube.fp.glsl"); + unsigned int fragmentShader; + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + { + int success; + char infoLog[512]; + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if(!success) { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + printf("fragment shader compile failed:\n%s\n", infoLog); + } + } + free(fragmentShaderSource); + + unsigned int shaderProgram; + shaderProgram = glCreateProgram(); + + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + + { + int success; + char infoLog[512]; + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + if(!success) { + glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); + printf("program link failed:\n%s\n", infoLog); + } + } + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + return shaderProgram; +} + +static int make_buffer(unsigned int target, + const void * data, + size_t size) +{ + unsigned int buffer; + glGenBuffers(1, &buffer); + glBindBuffer(target, buffer); + glBufferData(target, size, data, GL_DYNAMIC_DRAW); + return buffer; +} + +static float vertex_buffer_data[5 * 6 * 2 * 3] = { + // position // texture + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // top right + 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, // bottom right + -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // bottom left + + -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, // top left + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // top right + -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // bottom left +}; + +struct location { + struct { + unsigned int position; + unsigned int texture; + } attrib; + struct { + unsigned int texture1; + } uniform; +}; + +typedef struct { + float x; + float y; + float z; +} vec3; + +typedef struct { + float x; + float y; +} vec2; + +typedef struct { + int p; + int t; +} face; + +const vec3 position[] = { + {1.0, 1.0, -1.0}, + {1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0}, + {1.0, -1.0, 1.0}, + {-1.0, 1.0, -1.0}, + {-1.0, -1.0, -1.0}, + {-1.0, 1.0, 1.0}, + {-1.0, -1.0, 1.0}, +}; + +const vec2 texture[] = { + {1.0, 0.0}, + {0.0, 1.0}, + {0.0, 0.0}, + {1.0, 1.0}, +}; + +const face faces[] = { + {5,1}, {3,2}, {1,3}, + {3,1}, {8,2}, {4,3}, + {7,1}, {6,2}, {8,3}, + {2,1}, {8,2}, {6,3}, + {1,1}, {4,2}, {2,3}, + {5,1}, {2,2}, {6,3}, + {5,1}, {7,4}, {3,2}, + {3,1}, {7,4}, {8,2}, + {7,1}, {5,4}, {6,2}, + {2,1}, {4,4}, {8,2}, + {1,1}, {3,4}, {4,2}, + {5,1}, {1,4}, {2,2}, +}; + +static inline vec3 rotate(vec3 vertex, float theta) +{ + float x = vertex.x; + float y = vertex.y; + float z = vertex.z; + float t; + + t = y * cosf(theta) - z * sinf(theta); + z = y * sinf(theta) + z * cosf(theta); + y = t; + + float theta2 = 3.14 * sinf(theta / 2); + + t = x * cosf(theta2) - z * sinf(theta2); + z = x * sinf(theta2) + z * cosf(theta2); + x = t; + + return (vec3){x, y, z}; +} + +int main() +{ + glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11); + glfwInit(); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + float xscale, yscale; + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + printf("%f %f\n", xscale, yscale); + + //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); + + GLFWwindow* window = glfwCreateWindow(1600, 1200, "LearnOpenGL", NULL, NULL); + if (window == NULL) { + const char* description; + glfwGetError(&description); + printf("Failed to create GLFW window: %s\n", description); + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); + + int wwidth, wheight; + glfwGetWindowSize (window, + &wwidth, + &wheight); + printf("window : %d %d\n", wwidth, wheight); + + glViewport(0, 0, 1600, 1200); + //glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + int vertex_buffer = make_buffer(GL_ARRAY_BUFFER, + vertex_buffer_data, + (sizeof (vertex_buffer_data))); + + printf("compile start\n"); + unsigned int shaderProgram = compile_shaders(); + printf("compile end\n"); + + struct location location; + + location.attrib.position = glGetAttribLocation(shaderProgram, "pos"); + location.attrib.texture = glGetAttribLocation(shaderProgram, "tex"); + printf("attributes:\n position %u\n texture %u\n", + location.attrib.position, + location.attrib.texture); + + location.uniform.texture1 = glGetUniformLocation(shaderProgram, "texture1"); + printf("uniforms:\n texture %u\n", + location.uniform.texture1); + + unsigned int texture1; + glGenTextures(1, &texture1); + glActiveTexture(GL_TEXTURE0 + 0); + glBindTexture(GL_TEXTURE_2D, texture1); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + void * texture_buf = read_file("texture/butterfly_1024x1024_rgb888.data"); + assert(texture_buf != NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_buf); + free(texture_buf); + + float theta = 0; + while(!glfwWindowShouldClose(window)) { + if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + // + // render + // + + glUseProgram(shaderProgram); + + theta += 0.005f; + const int faces_length = (sizeof (faces)) / (sizeof (faces[0])); + const int vertex_buffer_length = (sizeof (vertex_buffer_data)) / (sizeof (vertex_buffer_data[0])); + assert(faces_length == (vertex_buffer_length / 5)); + for (int i = 0; i < faces_length; i++) { + vec3 p = rotate(position[faces[i].p - 1], theta); + p.x *= 0.2; + p.y *= 0.2; + p.z *= 0.2; + p.z += 0.5; + vec2 t = texture[faces[i].t - 1]; + + vertex_buffer_data[i * 5 + 0] = p.x; + vertex_buffer_data[i * 5 + 1] = p.y; + vertex_buffer_data[i * 5 + 2] = p.z; + vertex_buffer_data[i * 5 + 3] = t.x; + vertex_buffer_data[i * 5 + 4] = t.y; + + /* + printf("% .02f % .02f % .02f ; %01.01f %01.01f\n", p.x, p.y, p.z, t.x, t.y); + if (i % 3 == 2) + printf("\n"); + */ + } + //return 0; + + //printf("%f\n", theta); + + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, (sizeof (vertex_buffer_data)), vertex_buffer_data, GL_DYNAMIC_DRAW); + + glVertexAttribPointer(location.attrib.position, + 3, + GL_FLOAT, + GL_FALSE, + (sizeof (float)) * 5, + (void*)0 + ); + glVertexAttribPointer(location.attrib.texture, + 2, + GL_FLOAT, + GL_FALSE, + (sizeof (float)) * 5, + (void*)(3 * 4) + ); + glEnableVertexAttribArray(location.attrib.position); + glEnableVertexAttribArray(location.attrib.texture); + + glUniform1i(location.uniform.texture1, 0); + + glDrawArrays(GL_TRIANGLES, 0, 3 * 6 * 2); + + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwTerminate(); + + return 0; +} diff --git a/src/texture_cube.fp.glsl b/src/texture_cube.fp.glsl new file mode 100644 index 0000000..2bdba1d --- /dev/null +++ b/src/texture_cube.fp.glsl @@ -0,0 +1,8 @@ +#version 120 + +uniform sampler2D texture1; + +void main() +{ + gl_FragColor = texture2D(texture1, gl_TexCoord[0].xy); +} diff --git a/src/texture_cube.vp.glsl b/src/texture_cube.vp.glsl new file mode 100644 index 0000000..d6ccd84 --- /dev/null +++ b/src/texture_cube.vp.glsl @@ -0,0 +1,10 @@ +#version 120 + +attribute vec3 pos; +attribute vec2 tex; + +void main() +{ + gl_Position = vec4(pos.xy, -pos.z * pos.z, pos.z); + gl_TexCoord[0] = vec4(tex, 0, 0); +} diff --git a/src/texture_cube_depth.c b/src/texture_cube_depth.c new file mode 100644 index 0000000..f738c62 --- /dev/null +++ b/src/texture_cube_depth.c @@ -0,0 +1,353 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void * read_file(const char * filename) +{ + int fd = open(filename, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "open(%s): %s\n", filename, strerror(errno)); + return NULL; + } + + off_t size = lseek(fd, 0, SEEK_END); + if (size == (off_t)-1) { + fprintf(stderr, "lseek(%s, SEEK_END): %s\n", filename, strerror(errno)); + return NULL; + } + + off_t start = lseek(fd, 0, SEEK_SET); + if (start == (off_t)-1) { + fprintf(stderr, "lseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); + return NULL; + } + + void * buf = malloc(size+1); + + ssize_t read_size = read(fd, buf, size); + if (read_size == -1) { + fprintf(stderr, "read(%s): %s\n", filename, strerror(errno)); + return NULL; + } + ((char*)buf)[read_size] = 0; + + return buf; +} + +void framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +unsigned int compile_shaders() +{ + void * vertexShaderSource = read_file("src/texture_cube.vp.glsl"); + unsigned int vertexShader; + vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, (const char **)&vertexShaderSource, NULL); + glCompileShader(vertexShader); + { + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if(!success) { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + printf("vertex shader compile failed:\n%s\n", infoLog); + } + } + free(vertexShaderSource); + + void * fragmentShaderSource = read_file("src/texture_cube.fp.glsl"); + unsigned int fragmentShader; + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + { + int success; + char infoLog[512]; + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if(!success) { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + printf("fragment shader compile failed:\n%s\n", infoLog); + } + } + free(fragmentShaderSource); + + unsigned int shaderProgram; + shaderProgram = glCreateProgram(); + + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + + { + int success; + char infoLog[512]; + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + if(!success) { + glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); + printf("program link failed:\n%s\n", infoLog); + } + } + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + return shaderProgram; +} + +static int make_buffer(unsigned int target, + const void * data, + size_t size) +{ + unsigned int buffer; + glGenBuffers(1, &buffer); + glBindBuffer(target, buffer); + glBufferData(target, size, data, GL_DYNAMIC_DRAW); + return buffer; +} + +static float vertex_buffer_data[5 * 6 * 2 * 3] = { + // position // texture + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // top right + 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, // bottom right + -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // bottom left + + -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, // top left + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // top right + -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // bottom left +}; + +struct location { + struct { + unsigned int position; + unsigned int texture; + } attrib; + struct { + unsigned int texture1; + } uniform; +}; + +typedef struct { + float x; + float y; + float z; +} vec3; + +typedef struct { + float x; + float y; +} vec2; + +typedef struct { + int p; + int t; +} face; + +const vec3 position[] = { + {1.0, 1.0, -1.0}, + {1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0}, + {1.0, -1.0, 1.0}, + {-1.0, 1.0, -1.0}, + {-1.0, -1.0, -1.0}, + {-1.0, 1.0, 1.0}, + {-1.0, -1.0, 1.0}, +}; + +const vec2 texture[] = { + {1.0, 0.0}, + {0.0, 1.0}, + {0.0, 0.0}, + {1.0, 1.0}, +}; + +const face faces[] = { + {5,1}, {3,2}, {1,3}, + {3,1}, {8,2}, {4,3}, + {7,1}, {6,2}, {8,3}, + {2,1}, {8,2}, {6,3}, + {1,1}, {4,2}, {2,3}, + {5,1}, {2,2}, {6,3}, + {5,1}, {7,4}, {3,2}, + {3,1}, {7,4}, {8,2}, + {7,1}, {5,4}, {6,2}, + {2,1}, {4,4}, {8,2}, + {1,1}, {3,4}, {4,2}, + {5,1}, {1,4}, {2,2}, +}; + +static inline vec3 rotate(vec3 vertex, float theta) +{ + float x = vertex.x; + float y = vertex.y; + float z = vertex.z; + float t; + + t = y * cosf(theta) - z * sinf(theta); + z = y * sinf(theta) + z * cosf(theta); + y = t; + + float theta2 = 3.14 * sinf(theta / 2); + + t = x * cosf(theta2) - z * sinf(theta2); + z = x * sinf(theta2) + z * cosf(theta2); + x = t; + + return (vec3){x, y, z}; +} + +int main() +{ + glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11); + glfwInit(); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + float xscale, yscale; + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + printf("%f %f\n", xscale, yscale); + + //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); + + GLFWwindow* window = glfwCreateWindow(1600, 1200, "LearnOpenGL", NULL, NULL); + if (window == NULL) { + const char* description; + glfwGetError(&description); + printf("Failed to create GLFW window: %s\n", description); + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); + + int wwidth, wheight; + glfwGetWindowSize (window, + &wwidth, + &wheight); + printf("window : %d %d\n", wwidth, wheight); + + glViewport(0, 0, 1600, 1200); + //glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + int vertex_buffer = make_buffer(GL_ARRAY_BUFFER, + vertex_buffer_data, + (sizeof (vertex_buffer_data))); + + printf("compile start\n"); + unsigned int shaderProgram = compile_shaders(); + printf("compile end\n"); + + struct location location; + + location.attrib.position = glGetAttribLocation(shaderProgram, "pos"); + location.attrib.texture = glGetAttribLocation(shaderProgram, "tex"); + printf("attributes:\n position %u\n texture %u\n", + location.attrib.position, + location.attrib.texture); + + location.uniform.texture1 = glGetUniformLocation(shaderProgram, "texture1"); + printf("uniforms:\n texture %u\n", + location.uniform.texture1); + + unsigned int texture1; + glGenTextures(1, &texture1); + glActiveTexture(GL_TEXTURE0 + 0); + glBindTexture(GL_TEXTURE_2D, texture1); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + void * texture_buf = read_file("texture/butterfly_1024x1024_rgb888.data"); + assert(texture_buf != NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_buf); + free(texture_buf); + + float theta = 0; + while(!glfwWindowShouldClose(window)) { + if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + glClearDepthf(-1000.0f); + glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); + glDepthFunc(GL_GREATER); + glEnable(GL_DEPTH_TEST); + + // + // render + // + + glUseProgram(shaderProgram); + + theta += 0.005f; + const int faces_length = (sizeof (faces)) / (sizeof (faces[0])); + const int vertex_buffer_length = (sizeof (vertex_buffer_data)) / (sizeof (vertex_buffer_data[0])); + assert(faces_length == (vertex_buffer_length / 5)); + for (int i = 0; i < faces_length; i++) { + vec3 p = rotate(position[faces[i].p - 1], theta); + p.x *= 0.2; + p.y *= 0.2; + p.z *= 0.2; + p.z += 0.5; + vec2 t = texture[faces[i].t - 1]; + + vertex_buffer_data[i * 5 + 0] = p.x; + vertex_buffer_data[i * 5 + 1] = p.y; + vertex_buffer_data[i * 5 + 2] = p.z; + vertex_buffer_data[i * 5 + 3] = t.x; + vertex_buffer_data[i * 5 + 4] = t.y; + + /* + printf("% .02f % .02f % .02f ; %01.01f %01.01f\n", p.x, p.y, p.z, t.x, t.y); + if (i % 3 == 2) + printf("\n"); + */ + } + //return 0; + + //printf("%f\n", theta); + + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, (sizeof (vertex_buffer_data)), vertex_buffer_data, GL_DYNAMIC_DRAW); + + glVertexAttribPointer(location.attrib.position, + 3, + GL_FLOAT, + GL_FALSE, + (sizeof (float)) * 5, + (void*)0 + ); + glVertexAttribPointer(location.attrib.texture, + 2, + GL_FLOAT, + GL_FALSE, + (sizeof (float)) * 5, + (void*)(3 * 4) + ); + glEnableVertexAttribArray(location.attrib.position); + glEnableVertexAttribArray(location.attrib.texture); + + glUniform1i(location.uniform.texture1, 0); + + glDrawArrays(GL_TRIANGLES, 0, 3 * 6 * 2); + + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwTerminate(); + + return 0; +}