-
-
Save roxlu/11d7b8ee5db1283dc2a8 to your computer and use it in GitHub Desktop.
Light Rays- why noise on windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "LightRays.h" | |
#include <roxlu/opengl/Error.h> | |
LightRays::LightRays() | |
:w(0) | |
,h(0) | |
,tex(0) | |
,fbo(0) | |
,depth_buffer(0) | |
,frag_shader(0) | |
,vert_shader(0) | |
,prog(0) | |
,vbo(0) | |
,vao(0) | |
,exposure(0.0034f) | |
,decay(0.9999f) | |
,density(0.84f) | |
,weight(5.56f) | |
,light_x(0.0) | |
,light_y(0.0) | |
{ | |
} | |
void LightRays::createTexture(int texW, int texH, GLuint& texID) { | |
glEnable(GL_TEXTURE_2D); | |
glGenTextures(1, &texID); | |
glBindTexture(GL_TEXTURE_2D, texID); | |
glTexImage2D( | |
GL_TEXTURE_2D | |
,0 | |
,GL_RGBA | |
,texW | |
,texH | |
,0 | |
,GL_RGBA | |
,GL_UNSIGNED_BYTE | |
,NULL | |
); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
} | |
void LightRays::setup(int w, int h) { | |
this->w = w; | |
this->h = h; | |
this->dw = w; | |
this->dh = h; | |
// Create our fbo. | |
// ++++++++++++++++++++++++++++++++++++ | |
glGenFramebuffers(1, &fbo); | |
glBindFramebuffer(GL_FRAMEBUFFER, fbo); | |
// render to this texture. | |
createTexture(w,h,tex); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); | |
// apply fx into this texture. | |
createTexture(w,h,fx_tex); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fx_tex, 0); | |
// create depth buffer. | |
glGenRenderbuffers(1, &depth_buffer); | |
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer); | |
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); | |
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buffer); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
glBindRenderbuffer(GL_RENDERBUFFER, 0); | |
// Create shader | |
// ++++++++++++++++++++++++++++++++++++ | |
const char* vsp = LR_VS.c_str(); | |
const char* fsp = LR_FS.c_str(); | |
frag_shader = glCreateShader(GL_FRAGMENT_SHADER); | |
vert_shader = glCreateShader(GL_VERTEX_SHADER); | |
glShaderSource(vert_shader, 1, &(vsp), NULL); | |
glShaderSource(frag_shader, 1, &(fsp), NULL); | |
glCompileShader(vert_shader); | |
glCompileShader(frag_shader); | |
GLint result; | |
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &result); | |
if(!result) { | |
printf("Cannot compile vertex shader.\n"); | |
} | |
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &result); | |
if(!result) { | |
printf("Cannot compile fragment shader.\n"); | |
} | |
prog = glCreateProgram(); | |
glAttachShader(prog, vert_shader); | |
glAttachShader(prog, frag_shader); | |
glBindAttribLocation(prog, 0, "a_pos"); | |
glBindAttribLocation(prog, 1, "a_tex"); | |
glLinkProgram(prog); | |
glGetProgramiv(prog, GL_LINK_STATUS, &result); | |
if(!result) { | |
printf("Cannot link shaders.\n"); | |
} | |
// Create VAO + VBO for full screen quad | |
// ++++++++++++++++++++++++++++++++++++++ | |
LightRayVertex verts[4]; | |
float s = 1.0f; | |
// verts[0].set(-s, s, 0, 0, 0); | |
// verts[1].set( s, s, 0, 1, 0); | |
// verts[2].set( s,-s, 0, 1, 1); | |
// verts[3].set(-s,-s, 0, 0, 1); | |
verts[0].set(-s, s, 0, 0, 1); | |
verts[1].set( s, s, 0, 1, 1); | |
verts[2].set( s,-s, 0, 1, 0); | |
verts[3].set(-s,-s, 0, 0, 0); | |
#ifdef _WIN32 | |
glGenVertexArrays(1,&vao); | |
glBindVertexArray(vao); | |
#elif defined(__APPLE__) | |
glGenVertexArraysAPPLE(1,&vao); | |
glBindVertexArrayAPPLE(vao); | |
#else | |
#error I need to figure out, how to create a vertex array on your system? | |
#endif | |
glGenBuffers(1, &vbo); | |
glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(LightRayVertex) * 4, verts[0].getPtr(), GL_STATIC_DRAW); | |
glEnableVertexAttribArray(0); // pos | |
glEnableVertexAttribArray(1); // tex | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(LightRayVertex), (GLvoid*)offsetof(LightRayVertex, pos)); | |
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(LightRayVertex), (GLvoid*)offsetof(LightRayVertex, tex)); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
#ifdef _WIN32 | |
glBindVertexArray(0); | |
#elif define(__APPLE__) | |
glBindVertexArrayAPPLE(0); | |
#else | |
#error Cannot compile LightRays on this OS | |
#endif | |
} | |
void LightRays::resize(int w, int h) { | |
this->w = w; | |
this->h = h; | |
printf("New w/h: %d, %d\n", w,h); | |
} | |
void LightRays::bind() { | |
glBindFramebuffer(GL_FRAMEBUFFER, fbo); | |
glDrawBuffer(GL_COLOR_ATTACHMENT0); | |
glViewport(0,0,this->dw,this->dh); | |
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
} | |
void LightRays::unbind() { | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glViewport(0,0,this->w,this->h); | |
} | |
void LightRays::draw() { | |
glBindFramebuffer(GL_FRAMEBUFFER, fbo); | |
glDrawBuffer(GL_COLOR_ATTACHMENT1); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glViewport(0,0,this->dw,this->dh); | |
// bind | |
#ifdef _WIN32 | |
glBindVertexArray(vao); | |
#elif defined(__APPLE__) | |
glBindVertexArrayAPPLE(vao); | |
#else | |
#error Don't now how to draw on your machine (1) | |
#endif | |
glDisable(GL_DEPTH_TEST); | |
glDisable(GL_CULL_FACE); | |
// set shader vars. | |
glUseProgram(prog); | |
glEnable(GL_TEXTURE_2D); | |
glActiveTexture(GL_TEXTURE1); | |
glBindTexture(GL_TEXTURE_2D, tex); | |
glUniform1i(glGetUniformLocation(prog, "u_texture"), 1); | |
glUniform1f(glGetUniformLocation(prog, "u_exposure"), exposure); | |
glUniform1f(glGetUniformLocation(prog, "u_decay"), decay); | |
glUniform1f(glGetUniformLocation(prog, "u_density"), density); | |
glUniform1f(glGetUniformLocation(prog, "u_weight"), weight); | |
glUniform1f(glGetUniformLocation(prog, "u_light_x"), light_x); | |
glUniform1f(glGetUniformLocation(prog, "u_light_y"), light_y); | |
// apply effect | |
glUniform1i(glGetUniformLocation(prog, "u_mode"), 0); | |
glDrawArrays(GL_QUADS, 0, 4); | |
// draw full screen | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glActiveTexture(GL_TEXTURE1); | |
glBindTexture(GL_TEXTURE_2D, fx_tex); | |
glViewport(0,0,this->w,this->h); | |
glUniform1i(glGetUniformLocation(prog, "u_mode"), 1); | |
glDrawArrays(GL_QUADS, 0, 4); | |
// unbind | |
#ifdef _WIN32 | |
glBindVertexArray(0); | |
#elif defined(__APPLE__) | |
glBindVertexArrayAPPLE(0); | |
#else | |
#error Don't now how to draw on your machine (2) | |
#endif | |
glUseProgram(0); | |
// just make sure 0 and 1 unit are unbound. | |
glActiveTexture(GL_TEXTURE1); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ROXLU_LIGHTRAYSH | |
#define ROXLU_LIGHTRAYSH | |
#include <roxlu/opengl/OpenGL.h> | |
#include <string> | |
const std::string LR_VS = " \ | |
attribute vec4 a_pos; \ | |
attribute vec2 a_tex; \ | |
varying vec2 v_tex; \ | |
\ | |
void main() { \ | |
mat4 ident = mat4(1.0); \ | |
v_tex = a_tex; \ | |
gl_Position = ident * a_pos; \ | |
}\ | |
"; | |
const std::string LR_FS = " \ | |
uniform int u_mode; \ | |
uniform sampler2D u_texture; \ | |
uniform float u_exposure; \ | |
uniform float u_decay; \ | |
uniform float u_density; \ | |
uniform float u_weight; \ | |
uniform float u_light_x; \ | |
uniform float u_light_y; \ | |
const int NUM_SAMPLES = 100; \ | |
varying vec2 v_tex; \ | |
void main() { \ | |
if (u_mode == 0) { \ | |
//gl_FragColor = texture2D(u_texture, v_tex); // WHEN I ADD THIS LINE IT WORKS FINE ON WINDOWS \ | |
gl_FragColor.rgb = vec3(0.0, 0.0, 0.0); // THIS WORKS TOO ON WINDOWS! | |
vec2 pos_on_screen = vec2(u_light_x, u_light_y); \ | |
vec2 delta_texc = vec2(v_tex.st - pos_on_screen.xy); \ | |
vec2 texc = v_tex; \ | |
delta_texc *= 1.0 / float(NUM_SAMPLES) * u_density; \ | |
float illum_decay = 1.0; \ | |
for(int i = 0; i < NUM_SAMPLES; i++) { \ | |
texc -= delta_texc; \ | |
vec4 sample = texture2D(u_texture, texc); \ | |
sample *= illum_decay * u_weight; \ | |
gl_FragColor += sample; \ | |
illum_decay *= u_decay; \ | |
} \ | |
gl_FragColor *= u_exposure; \ | |
} \ | |
else if(u_mode == 1) { \ | |
gl_FragColor = texture2D(u_texture, v_tex); \ | |
gl_FragColor.a = 1.0; \ | |
} \ | |
\ | |
} "; | |
struct LightRayVertex { | |
float pos[3]; | |
float tex[2]; | |
LightRayVertex(){ | |
pos[0] = pos[1] = pos[2] = 0.0f; | |
tex[0] = tex[1] = 0.0f; | |
} | |
LightRayVertex(const float x, const float y, const float z, const float s, const float t) { | |
pos[0] = x; | |
pos[1] = y; | |
pos[2] = z; | |
tex[0] = s; | |
tex[1] = t; | |
} | |
void set(const float x, const float y, const float z, const float s, const float t) { | |
pos[0] = x; | |
pos[1] = y; | |
pos[2] = z; | |
tex[0] = s; | |
tex[1] = t; | |
} | |
const float* getPtr() { | |
return &pos[0]; | |
} | |
}; | |
class LightRays { | |
public: | |
LightRays(); | |
void setup(int w, int h); | |
void resize(int w, int h); | |
void bind(); | |
void unbind(); | |
void draw(); | |
void createTexture(int texW, int texH, GLuint& texID); | |
float exposure; | |
float decay; | |
float density; | |
float weight; | |
float light_x; | |
float light_y; | |
int w; | |
int h; | |
int dw; | |
int dh; | |
GLuint fbo; | |
GLuint tex; | |
GLuint fx_tex; | |
GLuint depth_buffer; | |
GLuint vbo; | |
GLuint vao; | |
GLuint prog; | |
GLuint frag_shader; | |
GLuint vert_shader; | |
}; | |
#endif |
Author
roxlu
commented
Jul 16, 2012
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment