Skip to content

Instantly share code, notes, and snippets.

@piusayowale
Created February 2, 2023 21:57
Show Gist options
  • Save piusayowale/2180d5f7147222274bf9900c5b76f0ff to your computer and use it in GitHub Desktop.
Save piusayowale/2180d5f7147222274bf9900c5b76f0ff to your computer and use it in GitHub Desktop.
rendering instance of sprite
#include <iostream>
#include <glad/glad.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
const char* vertex = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aCol;
layout (location = 2) in vec3 texCoord;
layout(std140) uniform transformBlock{
mat4 transform[5];
};
out vec3 color;
out vec3 texC;
uniform mat4 model;
uniform mat4 projection;
void main()
{
texC = texCoord;
color = aCol;
gl_Position = projection * transform[gl_InstanceID] * vec4(aPos.x, aPos.y, 0.0, 1.0);
}
)";
const char* fragment = R"(
#version 330 core
out vec4 FragColor;
in vec3 color;
in vec3 texC;
uniform sampler2D activeTexture;
void main()
{
FragColor = texture(activeTexture, texC.xy); // vec4(color, 1.0f);
}
)";
GLuint getProgram(const char* vertex, const char* fragment) {
// build and compile our shader program
// ------------------------------------
// vertex shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertex, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragment, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
struct Vector3 {
float x;
float y;
float z;
};
struct Vertex {
Vector3 vertice;
Vector3 color;
Vector3 texVert;
};
std::vector<glm::mat4> transformList;
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
// Also request a depth buffer
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_Window* window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1);
gladLoadGLLoader(SDL_GL_GetProcAddress);
SDL_Event event;
Vertex vertices[] = {
Vector3{1.0f, 1.0f, 0.0f}, Vector3{1.0f, 0.5f, 0.0f}, Vector3{1.0f, 1.0f, 0.0f},
Vector3{1.0f, 0.0f, 0.0f}, Vector3{1.0f, 0.5f, 0.0f}, Vector3{1.0f, 0.0f, 0.0f},
Vector3{0.0f, 0.0f, 0.0f}, Vector3{1.0f, 0.5f, 0.0f}, Vector3{0.0f, 0.0f, 0.0f},
Vector3{0.0f, 1.0f, 0.0f}, Vector3{1.0f, 0.5f, 0.0f}, Vector3{0.0f, 1.0f, 0.0f}
};
GLuint indices[] = {
0, 1, 3,
3, 2, 1
};
GLuint shaderProgram = getProgram(vertex, fragment);
unsigned int VBO, VAO, EBO, UBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertice));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texVert));
glEnableVertexAttribArray(2);
glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
model = glm::translate(model, glm::vec3(20.0f, 20.0f, 0.0f));
model = glm::scale(model, glm::vec3(glm::vec2(40, 40), 0.0f));
transformList.push_back(model);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(100.0f, 100.0f, 0.0f));
model = glm::scale(model, glm::vec3(glm::vec2(40, 40), 0.0f));
transformList.push_back(model);
glGenBuffers(1, &UBO);
glBindBuffer(GL_UNIFORM_BUFFER, UBO);
glBufferData(GL_UNIFORM_BUFFER, transformList.size() * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_UNIFORM_BUFFER, 0, transformList.size() * sizeof(glm::mat4), transformList.data());
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned int texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width = 0, height = 0, nchannels;
unsigned char* data = stbi_load("brick.png", &width, &height, &nchannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture\n";
}
stbi_image_free(data);
while (true)
{
glViewport(0, 0, 600, 600);
glClearColor(1.f, 0.f, 1.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
glm::mat4 projection(1.0f);
projection = glm::ortho(0.0f, (float)600, (float)600, 0.0f, -1.0f, 0.0f);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 0.1f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
GLuint bindingPoint = 1;
GLuint transformBlockIndex = glGetUniformBlockIndex(shaderProgram, "transformBlock");
glUniformBlockBinding(shaderProgram, transformBlockIndex, bindingPoint);
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, UBO);
/* unsigned int transformLoc = glGetUniformLocation(shaderProgram, "model");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model));*/
unsigned int projectLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(projectLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, 2);
if (SDL_PollEvent(&event)) {
switch (event.type)
{
case SDL_QUIT:
goto QUIT;
case SDL_KEYDOWN:
if (event.key.keysym.scancode == SDL_SCANCODE_Q) {
goto QUIT;
}
break;
default:
break;
}
}
SDL_GL_SwapWindow(window);
}
QUIT:
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