Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely.
- */
- /* This is a simple example of using GLSL shaders with SDL */
- #if 0 /* FIXME: Rework this using the 2.0 API */
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- printf("FIXME\n");
- return 0;
- }
- #else
- #include "SDL.h"
- #include "SDL_syswm.h"
- #if 1 // def HAVE_OPENGL
- #include "SDL_opengl.h"
- static SDL_Window * main_window = 0;
- static SDL_bool shaders_supported;
- static int current_shader = 0;
- enum {
- SHADER_COLOR,
- SHADER_TEXTURE,
- SHADER_TEXCOORDS,
- NUM_SHADERS
- };
- typedef struct {
- GLhandleARB program;
- GLhandleARB vert_shader;
- GLhandleARB frag_shader;
- const char *vert_source;
- const char *frag_source;
- } ShaderData;
- static ShaderData shaders[NUM_SHADERS] = {
- /* SHADER_COLOR */
- { 0, 0, 0,
- /* vertex shader */
- "varying vec4 v_color;\n"
- "\n"
- "void main()\n"
- "{\n"
- " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
- " v_color = gl_Color;\n"
- "}",
- /* fragment shader */
- "varying vec4 v_color;\n"
- "\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = v_color;\n"
- "}"
- },
- /* SHADER_TEXTURE */
- { 0, 0, 0,
- /* vertex shader */
- "varying vec4 v_color;\n"
- "varying vec2 v_texCoord;\n"
- "\n"
- "void main()\n"
- "{\n"
- " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
- " v_color = gl_Color;\n"
- " v_texCoord = vec2(gl_MultiTexCoord0);\n"
- "}",
- /* fragment shader */
- "varying vec4 v_color;\n"
- "varying vec2 v_texCoord;\n"
- "uniform sampler2D tex0;\n"
- "\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
- "}"
- },
- /* SHADER_TEXCOORDS */
- { 0, 0, 0,
- /* vertex shader */
- "varying vec2 v_texCoord;\n"
- "\n"
- "void main()\n"
- "{\n"
- " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
- " v_texCoord = vec2(gl_MultiTexCoord0);\n"
- "}",
- /* fragment shader */
- "varying vec2 v_texCoord;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec4 color;\n"
- " vec2 delta;\n"
- " float dist;\n"
- "\n"
- " delta = vec2(0.5, 0.5) - v_texCoord;\n"
- " dist = dot(delta, delta);\n"
- "\n"
- " color.r = v_texCoord.x;\n"
- " color.g = v_texCoord.x * v_texCoord.y;\n"
- " color.b = v_texCoord.y;\n"
- " color.a = 1.0 - (dist * 4.0);\n"
- " gl_FragColor = color;\n"
- "}"
- },
- };
- static PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
- static PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
- static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
- static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
- static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
- static PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
- static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
- static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
- static PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
- static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
- static PFNGLUNIFORM1IARBPROC glUniform1iARB;
- static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
- static SDL_bool CompileShader(GLhandleARB shader, const char *source)
- {
- GLint status;
- glShaderSourceARB(shader, 1, &source, NULL);
- glCompileShaderARB(shader);
- glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
- if (status == 0) {
- GLint length;
- char *info;
- glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
- info = SDL_stack_alloc(char, length+1);
- glGetInfoLogARB(shader, length, NULL, info);
- fprintf(stderr, "Failed to compile shader:\n%s\n%s", source, info);
- SDL_stack_free(info);
- return SDL_FALSE;
- } else {
- return SDL_TRUE;
- }
- }
- static SDL_bool CompileShaderProgram(ShaderData *data)
- {
- const int num_tmus_bound = 4;
- int i;
- GLint location;
- glGetError();
- /* Create one program object to rule them all */
- data->program = glCreateProgramObjectARB();
- /* Create the vertex shader */
- data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
- if (!CompileShader(data->vert_shader, data->vert_source)) {
- return SDL_FALSE;
- }
- /* Create the fragment shader */
- data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
- if (!CompileShader(data->frag_shader, data->frag_source)) {
- return SDL_FALSE;
- }
- /* ... and in the darkness bind them */
- glAttachObjectARB(data->program, data->vert_shader);
- glAttachObjectARB(data->program, data->frag_shader);
- glLinkProgramARB(data->program);
- /* Set up some uniform variables */
- glUseProgramObjectARB(data->program);
- for (i = 0; i < num_tmus_bound; ++i) {
- char tex_name[5];
- SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
- location = glGetUniformLocationARB(data->program, tex_name);
- if (location >= 0) {
- glUniform1iARB(location, i);
- }
- }
- glUseProgramObjectARB(0);
- return (glGetError() == GL_NO_ERROR);
- }
- static void DestroyShaderProgram(ShaderData *data)
- {
- if (shaders_supported) {
- glDeleteObjectARB(data->vert_shader);
- glDeleteObjectARB(data->frag_shader);
- glDeleteObjectARB(data->program);
- }
- }
- static SDL_bool InitShaders()
- {
- int i;
- /* Check for shader support */
- shaders_supported = SDL_FALSE;
- if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
- SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
- SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
- SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) {
- glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
- glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
- glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
- glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
- glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
- glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
- glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
- glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
- glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
- glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
- glUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
- glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
- if (glAttachObjectARB &&
- glCompileShaderARB &&
- glCreateProgramObjectARB &&
- glCreateShaderObjectARB &&
- glDeleteObjectARB &&
- glGetInfoLogARB &&
- glGetObjectParameterivARB &&
- glGetUniformLocationARB &&
- glLinkProgramARB &&
- glShaderSourceARB &&
- glUniform1iARB &&
- glUseProgramObjectARB) {
- shaders_supported = SDL_TRUE;
- }
- }
- if (!shaders_supported) {
- return SDL_FALSE;
- }
- /* Compile all the shaders */
- for (i = 0; i < NUM_SHADERS; ++i) {
- if (!CompileShaderProgram(&shaders[i])) {
- fprintf(stderr, "Unable to compile shader!\n");
- return SDL_FALSE;
- }
- }
- /* We're done! */
- return SDL_TRUE;
- }
- static void QuitShaders()
- {
- int i;
- for (i = 0; i < NUM_SHADERS; ++i) {
- DestroyShaderProgram(&shaders[i]);
- }
- }
- /* Quick utility function for texture creation */
- static int
- power_of_two(int input)
- {
- int value = 1;
- while (value < input) {
- value <<= 1;
- }
- return value;
- }
- GLuint
- SDL_GL_LoadTexture(SDL_Surface * surface, GLfloat * texcoord)
- {
- GLuint texture;
- int w, h;
- SDL_Surface *image;
- SDL_Rect area;
- Uint32 saved_flags;
- Uint8 saved_alpha;
- /* Use the surface width and height expanded to powers of 2 */
- w = power_of_two(surface->w);
- h = power_of_two(surface->h);
- texcoord[0] = 0.0f; /* Min X */
- texcoord[1] = 0.0f; /* Min Y */
- texcoord[2] = (GLfloat) surface->w / w; /* Max X */
- texcoord[3] = (GLfloat) surface->h / h; /* Max Y */
- image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
- #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
- 0x000000FF,
- 0x0000FF00, 0x00FF0000, 0xFF000000
- #else
- 0xFF000000,
- 0x00FF0000, 0x0000FF00, 0x000000FF
- #endif
- );
- if (image == NULL) {
- return 0;
- }
- /* Save the alpha blending attributes */
- // saved_flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
- // SDL_GetSurfaceAlphaMod(surface, &saved_alpha);
- // if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
- // SDL_SetAlpha(surface, 0, 0);
- // }
- /* Copy the surface into the GL texture image */
- area.x = 0;
- area.y = 0;
- area.w = surface->w;
- area.h = surface->h;
- SDL_BlitSurface(surface, &area, image, &area);
- /* Restore the alpha blending attributes */
- // if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
- // SDL_SetAlpha(surface, saved_flags, saved_alpha);
- // }
- /* Create an OpenGL texture for the image */
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
- SDL_FreeSurface(image); /* No longer needed */
- return texture;
- }
- /* A general OpenGL initialization function. Sets all of the initial parameters. */
- void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
- {
- GLdouble aspect;
- glViewport(0, 0, Width, Height);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
- glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
- glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
- glEnable(GL_DEPTH_TEST); // Enables Depth Testing
- glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity(); // Reset The Projection Matrix
- aspect = (GLdouble)Width / Height;
- glOrtho(-3.0, 3.0, -3.0 / aspect, 3.0 / aspect, 0.0, 1.0);
- glMatrixMode(GL_MODELVIEW);
- }
- /* The main drawing function. */
- void DrawGLScene(GLuint texture, GLfloat * texcoord)
- {
- /* Texture coordinate lookup, to make it simple */
- enum {
- MINX,
- MINY,
- MAXX,
- MAXY
- };
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
- glLoadIdentity(); // Reset The View
- glTranslatef(-1.5f,0.0f,0.0f); // Move Left 1.5 Units
- // draw a triangle (in smooth coloring mode)
- glBegin(GL_POLYGON); // start drawing a polygon
- glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
- glVertex3f( 0.0f, 1.0f, 0.0f); // Top
- glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
- glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
- glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
- glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
- glEnd(); // we're done with the polygon (smooth color interpolation)
- glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
- // Enable blending
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // draw a textured square (quadrilateral)
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture);
- glColor3f(1.0f,1.0f,1.0f);
- if (shaders_supported) {
- glUseProgramObjectARB(shaders[current_shader].program);
- }
- glBegin(GL_QUADS); // start drawing a polygon (4 sided)
- glTexCoord2f(texcoord[MINX], texcoord[MINY]);
- glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
- glTexCoord2f(texcoord[MAXX], texcoord[MINY]);
- glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
- glTexCoord2f(texcoord[MAXX], texcoord[MAXY]);
- glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
- glTexCoord2f(texcoord[MINX], texcoord[MAXY]);
- glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
- glEnd(); // done with the polygon
- if (shaders_supported) {
- glUseProgramObjectARB(0);
- }
- glDisable(GL_TEXTURE_2D);
- // swap buffers to display, since we're double buffered.
- SDL_GL_SwapWindow(main_window);
- }
- int main(int argc, char **argv)
- {
- int done;
- SDL_Surface *surface;
- GLuint texture;
- GLfloat texcoords[4];
- /* Initialize SDL for video output */
- if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
- fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
- exit(1);
- }
- SDL_Rect rect;
- rect.x = 0;
- rect.h = 0;
- rect.w = 640;
- rect.h = 480;
- SDL_GetDisplayBounds(0, &rect);
- main_window = SDL_CreateWindow("Shader Demo",
- (rect.w-640)/2,
- (rect.h-480)/2,
- 640,
- 480,
- SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS);
- printf("Using Video Driver: %s\n", SDL_GetCurrentVideoDriver());
- if(!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
- printf("Couldn't force OpenGL driver.\n");
- SDL_Renderer * renderer = SDL_CreateRenderer(main_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- if(!renderer)
- {
- printf("Could not create renderer: %s", SDL_GetError());
- exit(1);
- }
- // Print out information about the renderer.
- SDL_RendererInfo info;
- memset((void*)&info, 0, sizeof(SDL_RendererInfo));
- SDL_GetRendererInfo(renderer, &info);
- printf("Rendering using %s\n", info.name);
- if(info.flags & SDL_RENDERER_SOFTWARE)
- printf("SDL_RENDERER_SOFTWARE\n");
- else if(info.flags & SDL_RENDERER_ACCELERATED)
- printf("SDL_RENDERER_ACCELERATED\n");
- // TODO:
- surface = SDL_LoadBMP("/Users/jeremy.jurksztowicz/Desktop/icon.bmp");
- if ( ! surface ) {
- fprintf(stderr, "Unable to load icon.bmp: %s\n", SDL_GetError());
- SDL_Quit();
- exit(3);
- }
- texture = SDL_GL_LoadTexture(surface, texcoords);
- SDL_FreeSurface(surface);
- /* Loop, drawing and checking events */
- InitGL(640, 480);
- if (InitShaders()) {
- printf("Shaders supported, press SPACE to cycle them.\n");
- } else {
- printf("Shaders not supported!\n");
- }
- done = 0;
- while ( ! done ) {
- DrawGLScene(texture, texcoords);
- /* This could go in a separate function */
- { SDL_Event event;
- while ( SDL_PollEvent(&event) ) {
- if ( event.type == SDL_QUIT ) {
- done = 1;
- }
- if ( event.type == SDL_KEYDOWN ) {
- if ( event.key.keysym.sym == SDLK_SPACE ) {
- current_shader = (current_shader + 1) % NUM_SHADERS;
- printf("[[ USING SHADER ]] %d\n", current_shader);
- printf("**************************************************\nVERTEX: %s\n", shaders[current_shader].vert_source);
- printf("\n**********\nFRAGMENT: %s\n**************************************************\n", shaders[current_shader].frag_source);
- }
- if ( event.key.keysym.sym == SDLK_ESCAPE ) {
- done = 1;
- }
- }
- }
- }
- }
- QuitShaders();
- SDL_Quit();
- return 1;
- }
- #else /* HAVE_OPENGL */
- int
- main(int argc, char *argv[])
- {
- printf("No OpenGL support on this system\n");
- return 1;
- }
- #endif /* HAVE_OPENGL */
- #endif
- /* vi: set ts=4 sw=4 expandtab: */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement