SkyLok/shader_example/shader.cpp
2026-05-20 11:09:54 +02:00

148 lines
3.9 KiB
C++

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.hpp"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.hpp"
#include <fstream>
#include <vector>
#include <iostream>
std::string loadFile(const char* path)
{
std::ifstream f(path);
return std::string((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
}
GLuint compile(GLenum t, const std::string& src)
{
GLuint s = glCreateShader(t);
const char* c = src.c_str();
glShaderSource(s, 1, &c, NULL);
glCompileShader(s);
return s;
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* win = glfwCreateWindow(1,1,"",NULL,NULL);
glfwMakeContextCurrent(win);
glewInit();
// ---------------- LOAD IMAGES ----------------
int w,h,c;
unsigned char* img1 = stbi_load("frame1.jpg",&w,&h,&c,4);
unsigned char* img2 = stbi_load("frame2.jpg",&w,&h,&c,4);
if(!img1 || !img2)
{
std::cout << "image load failed\n";
return 0;
}
// ---------------- TEXTURES ----------------
GLuint texA, texB;
glGenTextures(1,&texA);
glGenTextures(1,&texB);
auto upload = [&](GLuint t, unsigned char* d)
{
glBindTexture(GL_TEXTURE_2D,t);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,d);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
};
upload(texA,img1);
upload(texB,img2);
// ---------------- SHADER ----------------
std::string frag = loadFile("motion.frag");
const char* vs =
"#version 330 core\n"
"layout(location=0) in vec2 pos;\n"
"out vec2 uv;\n"
"void main(){\n"
"uv = pos*0.5+0.5;\n"
"gl_Position = vec4(pos,0,1);\n"
"}";
GLuint v = compile(GL_VERTEX_SHADER,vs);
GLuint f = compile(GL_FRAGMENT_SHADER,frag);
GLuint prog = glCreateProgram();
glAttachShader(prog,v);
glAttachShader(prog,f);
glLinkProgram(prog);
// ---------------- QUAD (FIXED) ----------------
GLuint vao,vbo;
float quad[] = {
-1,-1,
1,-1,
-1, 1,
1, 1
};
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER,sizeof(quad),quad,GL_STATIC_DRAW);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
// ---------------- FBO ----------------
GLuint fbo,outTex;
glGenFramebuffers(1,&fbo);
glGenTextures(1,&outTex);
glBindTexture(GL_TEXTURE_2D,outTex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,outTex,0);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "FBO broken\n";
// ---------------- RENDER ----------------
glUseProgram(prog);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texA);
glUniform1i(glGetUniformLocation(prog,"texA"),0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,texB);
glUniform1i(glGetUniformLocation(prog,"texB"),1);
glViewport(0,0,w,h);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
// ---------------- READ BACK ----------------
std::vector<unsigned char> out(w*h*4);
glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,out.data());
stbi_write_jpg("frameO.jpg",w,h,4,out.data(),90);
std::cout << "done\n";
}