mobiground/opengl.c
2025-03-02 08:16:29 +02:00

202 lines
6 KiB
C

#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_opengl.h>
#include "opengl.h"
#include "readfile.h"
#include "math.h"
shaderProgram_t sp;
void resizeWindow ( int width, int height )
{
float n = 1.0f; // near
float f = 3.0f; // far
float fov = toRad(90); // 90 or 65 for console
float aspect = width / (float) height;
float t = n * tanf (fov / 2.0f);
float r = t * aspect;
float projMatr[] = {
n/r, 0, 0, 0,
0, n/t, 0, 0,
0, 0, (f+n)/(n-f), -1,
0, 0, 2.0f*n*f/(n-f), 0
}; // it's not rows, it's columns, 'GL_FALSE'
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "n=%.1f f=%.1f fov=%.2f aspect=%.2f t=%.2f r=%.2f\n", n, f, fov, aspect, t, r);
glUseProgram(sp.program);
glUniformMatrix4fv(sp.projMatrLoc, 1, GL_FALSE, projMatr);
glUseProgram(0);
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
}
void _matrix ( int width, int height )
{
float n = 1.0f; // near
float f = 3.0f; // far
float fov = toRad(90); // 90 or 65 for console
float aspect = width / (float) height;
float t = n * tanf (fov / 2.0f);
float r = t * aspect;
float projMatr[] = {
n/r, 0, 0, 0,
0, n/t, 0, 0,
0, 0, (f+n)/(n-f), -1,
0, 0, 2.0f*n*f/(n-f), 0
}; // it's not rows, it's columns, 'GL_FALSE'
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "n=%.1f f=%.1f fov=%.2f aspect=%.2f t=%.2f r=%.2f\n", n, f, fov, aspect, t, r);
glUseProgram(sp.program);
glUniformMatrix4fv(sp.projMatrLoc, 1, GL_FALSE, projMatr);
glUseProgram(0);
}
GLuint createShader ( const char *shaderFile, GLenum shaderType )
{
const char *strShaderType;
if (shaderType == GL_VERTEX_SHADER) {
strShaderType = "vertex";
} else if (shaderType == GL_GEOMETRY_SHADER) {
strShaderType = "geometry";
} else if (shaderType == GL_FRAGMENT_SHADER) {
strShaderType = "fragment";
} else {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Unrecognized shader type.");
exit(EXIT_FAILURE);
}
GLuint shader = glCreateShader(shaderType);
if (!shader) {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Error create shader type %s.", strShaderType);
exit(EXIT_FAILURE);
}
GLchar *content = readFile(shaderFile);
glShaderSource(shader, 1, (const GLchar **)&content, NULL);
SDL_free(content);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLen;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1));
glGetShaderInfoLog(shader, infoLen, NULL, info);
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Filed to compile %s shader:\n%s.", strShaderType, info);
exit(EXIT_FAILURE);
}
return shader;
}
void createProgram ( GLuint *shaders, int len )
{
sp.program = glCreateProgram();
if (!sp.program) {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Can't to create shader program.");
exit(EXIT_FAILURE);
}
for (int i = 0; i < len; i++) {
glAttachShader(sp.program, shaders[i]);
}
glLinkProgram(sp.program);
GLint status;
glGetProgramiv(sp.program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLen;
glGetProgramiv(sp.program, GL_INFO_LOG_LENGTH, &infoLen);
GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1));
glGetProgramInfoLog(sp.program, infoLen, NULL, info);
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Link failed: %s", info);
exit(EXIT_FAILURE);
}
}
void initVertexArray ( void )
{
glGenVertexArrays(1, &sp.vao);
glBindVertexArray(sp.vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, sp.vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sp.ibo);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *) (4*4*sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sp.ibo);
glBindVertexArray(0);
}
void createBuffer ( void )
{
GLushort indices[] = {
0, 1, 2,
0, 2, 3
};
float vertices[] = {
-1.0f, -1.0f, -2.0f, 1.0f, // left-bottom
-1.0f, 1.0f, -2.0f, 1.0f, // left-top
1.0f, 1.0f, -2.0f, 1.0f, // right-top
1.0f, -1.0f, -2.0f, 1.0f, // right-bottom
// colours
1.0f, 0.0f, 0.0f, 1.0f, // red
0.0f, 1.0f, 0.0f, 1.0f, // green
1.0f, 0.0f, 1.0f, 1.0f, // purple
1.0f, 1.0f, 0.0f, 1.0f // yellow
};
glGenBuffers(1, &sp.vbo);
glBindBuffer(GL_ARRAY_BUFFER, sp.vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &sp.ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sp.ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void setUniformLocation ( void )
{
sp.projMatrLoc = glGetUniformLocation(sp.program, "projMatr");
}
void startShaderProg ( void )
{
createBuffer();
initVertexArray();
GLuint shaders[] = {
createShader("vertex.glsl", GL_VERTEX_SHADER),
createShader("fragment.glsl", GL_FRAGMENT_SHADER)
};
int len = sizeof(shaders) / sizeof(shaders[0]);
createProgram(shaders, len);
for (int i = 0; i < len; i++) {
glDeleteShader(shaders[i]);
}
setUniformLocation();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
}
void _GLBuffer( void )
{
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(sp.program);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(sp.vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
glUseProgram(0);
}