Skip to content

Instantly share code, notes, and snippets.

@brndd

brndd/repro.cpp Secret

Created August 4, 2024 22:21
Show Gist options
  • Save brndd/2c94d3d3d76cc8b5426e00e8c0ce5e69 to your computer and use it in GitHub Desktop.
Save brndd/2c94d3d3d76cc8b5426e00e8c0ce5e69 to your computer and use it in GitHub Desktop.
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
// Vertex and fragment shader sources
const char* vertexShaderSource = R"(
#version 450
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform sampler2D heightmaps[2];
uniform float heightScale;
out vec3 vertexColor;
void main()
{
vertexColor = vec3(1.0);
ivec2 texel = ivec2(aPos.xz);
int index = 0;
index |= 1 * ((texel.x + texel.y) % 2);
vertexColor.r = float(index);
float height = 0.0;
height = texelFetch(heightmaps[index], texel, 0).r;
vec3 pos = vec3(aPos.x, height * 2.0f, aPos.z);
gl_Position = projection * view * model * vec4(pos, 1.0);
}
)";
const char* fragmentShaderSource = R"(
#version 450
out vec4 FragColor;
in vec3 vertexColor;
void main()
{
FragColor = vec4(vertexColor, 1.0);
}
)";
// Function to compile shader and create a program
GLuint createShaderProgram(const char* vertexSource, const char* fragmentSource) {
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cerr << "ERROR::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
// Function to create a procedurally generated 32x32 quad mesh
void createMesh(std::vector<float>& vertices, std::vector<unsigned int>& indices) {
int width = 32;
int height = 32;
float size = 1.0f;
float halfSize = size / 2.0f;
// Generate vertices
for (int y = 0; y <= height; ++y) {
for (int x = 0; x <= width; ++x) {
vertices.push_back(float(x));
vertices.push_back(0.0f);
vertices.push_back(float(y));
}
}
// Generate indices
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int start = y * (width + 1) + x;
indices.push_back(start);
indices.push_back(start + width + 1);
indices.push_back(start + 1);
indices.push_back(start + 1);
indices.push_back(start + width + 1);
indices.push_back(start + width + 2);
}
}
}
// Function to generate and upload procedural textures
void generateTextures(GLuint textures[2]) {
// Texture dimensions
const int texSize = 32;
// Generate black and white textures
std::vector<unsigned short> blackTexture(texSize * texSize, 0); // Black texture
std::vector<unsigned short> whiteTexture(texSize * texSize, 65535); // White texture (16-bit max value)
// Create OpenGL textures
glGenTextures(2, textures);
// Black texture
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, texSize, texSize, 0, GL_RED, GL_UNSIGNED_SHORT, blackTexture.data());
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);
// White texture
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, texSize, texSize, 0, GL_RED, GL_UNSIGNED_SHORT, whiteTexture.data());
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);
}
int main(int argc, char* argv[]) {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
return -1;
}
// Set SDL attributes for OpenGL
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// Create a window
SDL_Window* window = SDL_CreateWindow("Procedural 32x32 Quad Mesh with Heightmaps", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
if (!window) {
std::cerr << "Failed to create SDL window: " << SDL_GetError() << std::endl;
SDL_Quit();
return -1;
}
// Create OpenGL context
SDL_GLContext context = SDL_GL_CreateContext(window);
if (!context) {
std::cerr << "Failed to create OpenGL context: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Initialize GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Generate procedural heightmap textures
GLuint heightmapTextures[2];
generateTextures(heightmapTextures);
// Define vertices and indices for the mesh
std::vector<float> vertices;
std::vector<unsigned int> indices;
createMesh(vertices, indices);
// Create and bind VBO and VAO
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Create shader program
GLuint shaderProgram = createShaderProgram(vertexShaderSource, fragmentShaderSource);
// Set up transformation matrices
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(-16.0f, 0.0f, -16.0f));
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -10.0f, -50.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
// Main loop
bool running = true;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
}
// Clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use shader program
glUseProgram(shaderProgram);
// Pass transformation matrices to the shader
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Bind heightmap textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, heightmapTextures[0]);
glUniform1i(glGetUniformLocation(shaderProgram, "heightmaps[0]"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, heightmapTextures[1]);
glUniform1i(glGetUniformLocation(shaderProgram, "heightmaps[1]"), 1);
// Set height scale
glUniform1f(glGetUniformLocation(shaderProgram, "heightScale"), 5.0f);
// Render the mesh
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
// Swap buffers
SDL_GL_SwapWindow(window);
}
// Cleanup
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shaderProgram);
glDeleteTextures(2, heightmapTextures);
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment