OpenGL: Attachable shaders for GL2

This commit is contained in:
Jeffrey Pfau 2015-10-29 23:53:13 -07:00
parent f689bfcb2b
commit 206f38a47c
2 changed files with 113 additions and 2 deletions
src/platform/opengl

View File

@ -16,6 +16,15 @@ static const char* const _vertexShader =
" texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
"}";
static const char* const _nullVertexShader =
"attribute vec4 position;\n"
"varying vec2 texCoord;\n"
"void main() {\n"
" gl_Position = position * vec4(1.0, 1.0, 1.0, 1.0);\n"
" texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5);\n"
"}";
static const char* const _fragmentShader =
"varying vec2 texCoord;\n"
"uniform sampler2D tex;\n"
@ -56,16 +65,23 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
context->program = glCreateProgram();
context->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
context->vertexShader = glCreateShader(GL_VERTEX_SHADER);
context->nullVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(context->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
glShaderSource(context->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
glShaderSource(context->nullVertexShader, 1, (const GLchar**) &_nullVertexShader, 0);
glAttachShader(context->program, context->vertexShader);
glAttachShader(context->program, context->fragmentShader);
char log[1024];
glCompileShader(context->fragmentShader);
glCompileShader(context->vertexShader);
glCompileShader(context->nullVertexShader);
glGetShaderInfoLog(context->fragmentShader, 1024, 0, log);
printf("%s\n", log);
glGetShaderInfoLog(context->vertexShader, 1024, 0, log);
printf("%s\n", log);
glGetShaderInfoLog(context->nullVertexShader, 1024, 0, log);
printf("%s\n", log);
glLinkProgram(context->program);
glGetProgramInfoLog(context->program, 1024, 0, log);
printf("%s\n", log);
@ -79,6 +95,7 @@ static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
glDeleteTextures(1, &context->tex);
glDeleteShader(context->fragmentShader);
glDeleteShader(context->vertexShader);
glDeleteShader(context->nullVertexShader);
glDeleteProgram(context->program);
}
@ -106,10 +123,27 @@ static void GBAGLES2ContextClear(struct VideoBackend* v) {
void GBAGLES2ContextDrawFrame(struct VideoBackend* v) {
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
glUseProgram(context->program);
glUniform1i(context->texLocation, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, context->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, v->filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, v->filter ? GL_LINEAR : GL_NEAREST);
if (context->shader) {
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glViewport(0, 0, context->shader->width, context->shader->height);
glBindFramebuffer(GL_FRAMEBUFFER, context->shader->fbo);
glUseProgram(context->shader->program);
glUniform1i(context->shader->texLocation, 0);
glVertexAttribPointer(context->shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
glEnableVertexAttribArray(context->shader->positionLocation);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, context->shader->tex);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
glUseProgram(context->program);
glUniform1i(context->texLocation, 0);
glVertexAttribPointer(context->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
glEnableVertexAttribArray(context->positionLocation);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@ -140,4 +174,62 @@ void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
context->d.drawFrame = GBAGLES2ContextDrawFrame;
context->d.setMessage = 0;
context->d.clearMessage = 0;
context->shader = 0;
}
void GBAGLES2ShaderInit(struct GBAGLES2Shader* shader, const char* src, int width, int height, bool filter) {
shader->width = width > 0 ? width : 256;
shader->height = height > 0 ? height : 256;
glGenFramebuffers(1, &shader->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, shader->fbo);
glGenTextures(1, &shader->tex);
glBindTexture(GL_TEXTURE_2D, shader->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : 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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, shader->width, shader->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shader->tex, 0);
shader->program = glCreateProgram();
shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(shader->fragmentShader, 1, (const GLchar**) &src, 0);
glAttachShader(shader->program, shader->fragmentShader);
glCompileShader(shader->fragmentShader);
char log[1024];
glGetShaderInfoLog(shader->fragmentShader, 1024, 0, log);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void GBAGLES2ShaderDeinit(struct GBAGLES2Shader* shader) {
glDeleteTextures(1, &shader->tex);
glDeleteShader(shader->fragmentShader);
glDeleteProgram(shader->program);
}
void GBAGLES2ShaderAttach(struct GBAGLES2Context* context, struct GBAGLES2Shader* shader) {
if (context->shader) {
if (context->shader == shader) {
return;
}
GBAGLES2ShaderDetach(context);
}
context->shader = shader;
glAttachShader(shader->program, context->nullVertexShader);
char log[1024];
glLinkProgram(shader->program);
glGetProgramInfoLog(shader->program, 1024, 0, log);
printf("%s\n", log);
shader->texLocation = glGetUniformLocation(shader->program, "tex");
shader->positionLocation = glGetAttribLocation(shader->program, "position");
}
void GBAGLES2ShaderDetach(struct GBAGLES2Context* context) {
if (!context->shader) {
return;
}
glDetachShader(context->shader->program, context->nullVertexShader);
context->shader = 0;
}

View File

@ -18,18 +18,37 @@
#include "platform/video-backend.h"
struct GBAGLES2Shader {
unsigned width;
unsigned height;
GLuint tex;
GLuint fbo;
GLuint fragmentShader;
GLuint program;
GLuint texLocation;
GLuint positionLocation;
};
struct GBAGLES2Context {
struct VideoBackend d;
GLuint tex;
GLuint fragmentShader;
GLuint vertexShader;
GLuint nullVertexShader;
GLuint program;
GLuint bufferObject;
GLuint texLocation;
GLuint positionLocation;
struct GBAGLES2Shader* shader;
};
void GBAGLES2ContextCreate(struct GBAGLES2Context*);
void GBAGLES2ShaderInit(struct GBAGLES2Shader*, const char*, int width, int height, bool filter);
void GBAGLES2ShaderDeinit(struct GBAGLES2Shader*);
void GBAGLES2ShaderAttach(struct GBAGLES2Context*, struct GBAGLES2Shader*);
void GBAGLES2ShaderDetach(struct GBAGLES2Context*);
#endif