test/testshader.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
slouken@5535
     1
/*
slouken@10737
     2
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@5535
     3
slouken@5535
     4
  This software is provided 'as-is', without any express or implied
slouken@5535
     5
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     6
  arising from the use of this software.
slouken@5535
     7
slouken@5535
     8
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
     9
  including commercial applications, and to alter it and redistribute it
slouken@5535
    10
  freely.
slouken@5535
    11
*/
slouken@5232
    12
/* This is a simple example of using GLSL shaders with SDL */
slouken@5232
    13
slouken@5232
    14
#include "SDL.h"
slouken@5232
    15
slouken@5232
    16
#ifdef HAVE_OPENGL
slouken@5232
    17
slouken@5232
    18
#include "SDL_opengl.h"
slouken@5232
    19
slouken@5232
    20
slouken@5232
    21
static SDL_bool shaders_supported;
slouken@5232
    22
static int      current_shader = 0;
slouken@5232
    23
slouken@5232
    24
enum {
slouken@5232
    25
    SHADER_COLOR,
slouken@5232
    26
    SHADER_TEXTURE,
slouken@5232
    27
    SHADER_TEXCOORDS,
slouken@5232
    28
    NUM_SHADERS
slouken@5232
    29
};
slouken@5232
    30
slouken@5232
    31
typedef struct {
icculus@5641
    32
    GLhandleARB program;
icculus@5641
    33
    GLhandleARB vert_shader;
icculus@5641
    34
    GLhandleARB frag_shader;
slouken@5232
    35
    const char *vert_source;
slouken@5232
    36
    const char *frag_source;
slouken@5232
    37
} ShaderData;
slouken@5232
    38
slouken@5232
    39
static ShaderData shaders[NUM_SHADERS] = {
slouken@5232
    40
slouken@5232
    41
    /* SHADER_COLOR */
slouken@5232
    42
    { 0, 0, 0,
slouken@5232
    43
        /* vertex shader */
slouken@5232
    44
"varying vec4 v_color;\n"
slouken@5232
    45
"\n"
slouken@5232
    46
"void main()\n"
slouken@5232
    47
"{\n"
slouken@5232
    48
"    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
slouken@5232
    49
"    v_color = gl_Color;\n"
slouken@5232
    50
"}",
slouken@5232
    51
        /* fragment shader */
slouken@5232
    52
"varying vec4 v_color;\n"
slouken@5232
    53
"\n"
slouken@5232
    54
"void main()\n"
slouken@5232
    55
"{\n"
slouken@5232
    56
"    gl_FragColor = v_color;\n"
slouken@5232
    57
"}"
slouken@5232
    58
    },
slouken@5232
    59
slouken@5232
    60
    /* SHADER_TEXTURE */
slouken@5232
    61
    { 0, 0, 0,
slouken@5232
    62
        /* vertex shader */
slouken@5232
    63
"varying vec4 v_color;\n"
slouken@5232
    64
"varying vec2 v_texCoord;\n"
slouken@5232
    65
"\n"
slouken@5232
    66
"void main()\n"
slouken@5232
    67
"{\n"
slouken@5232
    68
"    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
slouken@5232
    69
"    v_color = gl_Color;\n"
slouken@5232
    70
"    v_texCoord = vec2(gl_MultiTexCoord0);\n"
slouken@5232
    71
"}",
slouken@5232
    72
        /* fragment shader */
slouken@5232
    73
"varying vec4 v_color;\n"
slouken@5232
    74
"varying vec2 v_texCoord;\n"
slouken@5232
    75
"uniform sampler2D tex0;\n"
slouken@5232
    76
"\n"
slouken@5232
    77
"void main()\n"
slouken@5232
    78
"{\n"
slouken@5232
    79
"    gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
slouken@5232
    80
"}"
slouken@5232
    81
    },
slouken@5232
    82
slouken@5232
    83
    /* SHADER_TEXCOORDS */
slouken@5232
    84
    { 0, 0, 0,
slouken@5232
    85
        /* vertex shader */
slouken@5232
    86
"varying vec2 v_texCoord;\n"
slouken@5232
    87
"\n"
slouken@5232
    88
"void main()\n"
slouken@5232
    89
"{\n"
slouken@5232
    90
"    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
slouken@5232
    91
"    v_texCoord = vec2(gl_MultiTexCoord0);\n"
slouken@5232
    92
"}",
slouken@5232
    93
        /* fragment shader */
slouken@5232
    94
"varying vec2 v_texCoord;\n"
slouken@5232
    95
"\n"
slouken@5232
    96
"void main()\n"
slouken@5232
    97
"{\n"
slouken@5232
    98
"    vec4 color;\n"
slouken@5232
    99
"    vec2 delta;\n"
slouken@5232
   100
"    float dist;\n"
slouken@5232
   101
"\n"
slouken@5232
   102
"    delta = vec2(0.5, 0.5) - v_texCoord;\n"
slouken@5232
   103
"    dist = dot(delta, delta);\n"
slouken@5232
   104
"\n"
slouken@5232
   105
"    color.r = v_texCoord.x;\n"
slouken@5232
   106
"    color.g = v_texCoord.x * v_texCoord.y;\n"
slouken@5232
   107
"    color.b = v_texCoord.y;\n"
slouken@5232
   108
"    color.a = 1.0 - (dist * 4.0);\n"
slouken@5232
   109
"    gl_FragColor = color;\n"
slouken@5232
   110
"}"
slouken@5232
   111
    },
slouken@5232
   112
};
slouken@7191
   113
slouken@5232
   114
static PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
slouken@5232
   115
static PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
slouken@5232
   116
static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
slouken@5232
   117
static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
slouken@5232
   118
static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
slouken@5232
   119
static PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
slouken@5232
   120
static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
slouken@5232
   121
static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
slouken@5232
   122
static PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
slouken@5232
   123
static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
slouken@5232
   124
static PFNGLUNIFORM1IARBPROC glUniform1iARB;
slouken@5232
   125
static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
slouken@5232
   126
icculus@5641
   127
static SDL_bool CompileShader(GLhandleARB shader, const char *source)
slouken@5232
   128
{
slouken@5232
   129
    GLint status;
slouken@5232
   130
slouken@5232
   131
    glShaderSourceARB(shader, 1, &source, NULL);
slouken@5232
   132
    glCompileShaderARB(shader);
slouken@5232
   133
    glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
slouken@5232
   134
    if (status == 0) {
slouken@5232
   135
        GLint length;
slouken@5232
   136
        char *info;
slouken@5232
   137
slouken@5232
   138
        glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
slouken@5232
   139
        info = SDL_stack_alloc(char, length+1);
slouken@5232
   140
        glGetInfoLogARB(shader, length, NULL, info);
aschiffler@7639
   141
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
slouken@5232
   142
        SDL_stack_free(info);
slouken@5232
   143
slouken@5232
   144
        return SDL_FALSE;
slouken@5232
   145
    } else {
slouken@5232
   146
        return SDL_TRUE;
slouken@5232
   147
    }
slouken@5232
   148
}
slouken@5232
   149
slouken@5232
   150
static SDL_bool CompileShaderProgram(ShaderData *data)
slouken@5232
   151
{
slouken@5232
   152
    const int num_tmus_bound = 4;
slouken@5232
   153
    int i;
slouken@5232
   154
    GLint location;
slouken@5232
   155
slouken@5232
   156
    glGetError();
slouken@5232
   157
slouken@5232
   158
    /* Create one program object to rule them all */
slouken@5232
   159
    data->program = glCreateProgramObjectARB();
slouken@5232
   160
slouken@5232
   161
    /* Create the vertex shader */
slouken@5232
   162
    data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
slouken@5232
   163
    if (!CompileShader(data->vert_shader, data->vert_source)) {
slouken@5232
   164
        return SDL_FALSE;
slouken@5232
   165
    }
slouken@5232
   166
slouken@5232
   167
    /* Create the fragment shader */
slouken@5232
   168
    data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
slouken@5232
   169
    if (!CompileShader(data->frag_shader, data->frag_source)) {
slouken@5232
   170
        return SDL_FALSE;
slouken@5232
   171
    }
slouken@5232
   172
slouken@5232
   173
    /* ... and in the darkness bind them */
slouken@5232
   174
    glAttachObjectARB(data->program, data->vert_shader);
slouken@5232
   175
    glAttachObjectARB(data->program, data->frag_shader);
slouken@5232
   176
    glLinkProgramARB(data->program);
slouken@5232
   177
slouken@5232
   178
    /* Set up some uniform variables */
slouken@5232
   179
    glUseProgramObjectARB(data->program);
slouken@5232
   180
    for (i = 0; i < num_tmus_bound; ++i) {
slouken@5232
   181
        char tex_name[5];
slouken@5232
   182
        SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
slouken@5232
   183
        location = glGetUniformLocationARB(data->program, tex_name);
slouken@5232
   184
        if (location >= 0) {
slouken@5232
   185
            glUniform1iARB(location, i);
slouken@5232
   186
        }
slouken@5232
   187
    }
slouken@5232
   188
    glUseProgramObjectARB(0);
slouken@7191
   189
slouken@7996
   190
    return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE;
slouken@5232
   191
}
slouken@5232
   192
slouken@5232
   193
static void DestroyShaderProgram(ShaderData *data)
slouken@5232
   194
{
slouken@5236
   195
    if (shaders_supported) {
slouken@5236
   196
        glDeleteObjectARB(data->vert_shader);
slouken@5236
   197
        glDeleteObjectARB(data->frag_shader);
slouken@5236
   198
        glDeleteObjectARB(data->program);
slouken@5236
   199
    }
slouken@5232
   200
}
slouken@5232
   201
slouken@5232
   202
static SDL_bool InitShaders()
slouken@5232
   203
{
slouken@5232
   204
    int i;
slouken@5232
   205
slouken@5232
   206
    /* Check for shader support */
slouken@5232
   207
    shaders_supported = SDL_FALSE;
slouken@5232
   208
    if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
slouken@5232
   209
        SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
slouken@5232
   210
        SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
slouken@5232
   211
        SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) {
slouken@5232
   212
        glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
slouken@5232
   213
        glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
slouken@5232
   214
        glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
slouken@5232
   215
        glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
slouken@5232
   216
        glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
slouken@5232
   217
        glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
slouken@5232
   218
        glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
slouken@5232
   219
        glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
slouken@5232
   220
        glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
slouken@5232
   221
        glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
slouken@5232
   222
        glUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
slouken@5232
   223
        glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
slouken@5232
   224
        if (glAttachObjectARB &&
slouken@5232
   225
            glCompileShaderARB &&
slouken@5232
   226
            glCreateProgramObjectARB &&
slouken@5232
   227
            glCreateShaderObjectARB &&
slouken@5232
   228
            glDeleteObjectARB &&
slouken@5232
   229
            glGetInfoLogARB &&
slouken@5232
   230
            glGetObjectParameterivARB &&
slouken@5232
   231
            glGetUniformLocationARB &&
slouken@5232
   232
            glLinkProgramARB &&
slouken@5232
   233
            glShaderSourceARB &&
slouken@5232
   234
            glUniform1iARB &&
slouken@5232
   235
            glUseProgramObjectARB) {
slouken@5232
   236
            shaders_supported = SDL_TRUE;
slouken@5232
   237
        }
slouken@5232
   238
    }
slouken@5232
   239
slouken@5232
   240
    if (!shaders_supported) {
slouken@5232
   241
        return SDL_FALSE;
slouken@5232
   242
    }
slouken@5232
   243
slouken@5232
   244
    /* Compile all the shaders */
slouken@5232
   245
    for (i = 0; i < NUM_SHADERS; ++i) {
slouken@5232
   246
        if (!CompileShaderProgram(&shaders[i])) {
aschiffler@7639
   247
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to compile shader!\n");
slouken@5232
   248
            return SDL_FALSE;
slouken@5232
   249
        }
slouken@5232
   250
    }
slouken@5232
   251
slouken@5232
   252
    /* We're done! */
slouken@5232
   253
    return SDL_TRUE;
slouken@5232
   254
}
slouken@5232
   255
slouken@5232
   256
static void QuitShaders()
slouken@5232
   257
{
slouken@5232
   258
    int i;
slouken@5232
   259
slouken@5232
   260
    for (i = 0; i < NUM_SHADERS; ++i) {
slouken@5232
   261
        DestroyShaderProgram(&shaders[i]);
slouken@5232
   262
    }
slouken@5232
   263
}
slouken@5232
   264
slouken@5232
   265
/* Quick utility function for texture creation */
slouken@5232
   266
static int
slouken@5232
   267
power_of_two(int input)
slouken@5232
   268
{
slouken@5232
   269
    int value = 1;
slouken@5232
   270
slouken@5232
   271
    while (value < input) {
slouken@5232
   272
        value <<= 1;
slouken@5232
   273
    }
slouken@5232
   274
    return value;
slouken@5232
   275
}
slouken@5232
   276
slouken@5232
   277
GLuint
slouken@5232
   278
SDL_GL_LoadTexture(SDL_Surface * surface, GLfloat * texcoord)
slouken@5232
   279
{
slouken@5232
   280
    GLuint texture;
slouken@5232
   281
    int w, h;
slouken@5232
   282
    SDL_Surface *image;
slouken@5232
   283
    SDL_Rect area;
slouken@7324
   284
    SDL_BlendMode saved_mode;
slouken@5232
   285
slouken@5232
   286
    /* Use the surface width and height expanded to powers of 2 */
slouken@5232
   287
    w = power_of_two(surface->w);
slouken@5232
   288
    h = power_of_two(surface->h);
slouken@5232
   289
    texcoord[0] = 0.0f;         /* Min X */
slouken@5232
   290
    texcoord[1] = 0.0f;         /* Min Y */
slouken@5232
   291
    texcoord[2] = (GLfloat) surface->w / w;     /* Max X */
slouken@5232
   292
    texcoord[3] = (GLfloat) surface->h / h;     /* Max Y */
slouken@5232
   293
slouken@5232
   294
    image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
slouken@5232
   295
#if SDL_BYTEORDER == SDL_LIL_ENDIAN     /* OpenGL RGBA masks */
slouken@5232
   296
                                 0x000000FF,
slouken@5232
   297
                                 0x0000FF00, 0x00FF0000, 0xFF000000
slouken@5232
   298
#else
slouken@5232
   299
                                 0xFF000000,
slouken@5232
   300
                                 0x00FF0000, 0x0000FF00, 0x000000FF
slouken@5232
   301
#endif
slouken@5232
   302
        );
slouken@5232
   303
    if (image == NULL) {
slouken@5232
   304
        return 0;
slouken@5232
   305
    }
slouken@5232
   306
slouken@5232
   307
    /* Save the alpha blending attributes */
slouken@7324
   308
    SDL_GetSurfaceBlendMode(surface, &saved_mode);
slouken@7324
   309
    SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
slouken@5232
   310
slouken@5232
   311
    /* Copy the surface into the GL texture image */
slouken@5232
   312
    area.x = 0;
slouken@5232
   313
    area.y = 0;
slouken@5232
   314
    area.w = surface->w;
slouken@5232
   315
    area.h = surface->h;
slouken@5232
   316
    SDL_BlitSurface(surface, &area, image, &area);
slouken@5232
   317
slouken@5232
   318
    /* Restore the alpha blending attributes */
slouken@7324
   319
    SDL_SetSurfaceBlendMode(surface, saved_mode);
slouken@5232
   320
slouken@5232
   321
    /* Create an OpenGL texture for the image */
slouken@5232
   322
    glGenTextures(1, &texture);
slouken@5232
   323
    glBindTexture(GL_TEXTURE_2D, texture);
slouken@5232
   324
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
slouken@5232
   325
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
slouken@5232
   326
    glTexImage2D(GL_TEXTURE_2D,
slouken@5232
   327
                 0,
slouken@5232
   328
                 GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
slouken@5232
   329
    SDL_FreeSurface(image);     /* No longer needed */
slouken@5232
   330
slouken@5232
   331
    return texture;
slouken@5232
   332
}
slouken@5232
   333
slouken@5232
   334
/* A general OpenGL initialization function.    Sets all of the initial parameters. */
gabomdq@7663
   335
void InitGL(int Width, int Height)                    /* We call this right after our OpenGL window is created. */
slouken@5232
   336
{
slouken@5232
   337
    GLdouble aspect;
slouken@5232
   338
slouken@5232
   339
    glViewport(0, 0, Width, Height);
gabomdq@7663
   340
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);        /* This Will Clear The Background Color To Black */
gabomdq@7663
   341
    glClearDepth(1.0);                /* Enables Clearing Of The Depth Buffer */
gabomdq@7663
   342
    glDepthFunc(GL_LESS);                /* The Type Of Depth Test To Do */
gabomdq@7663
   343
    glEnable(GL_DEPTH_TEST);            /* Enables Depth Testing */
gabomdq@7663
   344
    glShadeModel(GL_SMOOTH);            /* Enables Smooth Color Shading */
slouken@5232
   345
slouken@5232
   346
    glMatrixMode(GL_PROJECTION);
gabomdq@7663
   347
    glLoadIdentity();                /* Reset The Projection Matrix */
slouken@5232
   348
slouken@5232
   349
    aspect = (GLdouble)Width / Height;
slouken@5232
   350
    glOrtho(-3.0, 3.0, -3.0 / aspect, 3.0 / aspect, 0.0, 1.0);
slouken@5232
   351
slouken@5232
   352
    glMatrixMode(GL_MODELVIEW);
slouken@5232
   353
}
slouken@5232
   354
slouken@5232
   355
/* The main drawing function. */
slouken@7323
   356
void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat * texcoord)
slouken@5232
   357
{
slouken@5232
   358
    /* Texture coordinate lookup, to make it simple */
slouken@5232
   359
    enum {
slouken@5232
   360
        MINX,
slouken@5232
   361
        MINY,
slouken@5232
   362
        MAXX,
slouken@5232
   363
        MAXY
slouken@5232
   364
    };
slouken@5232
   365
gabomdq@7663
   366
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        /* Clear The Screen And The Depth Buffer */
gabomdq@7663
   367
    glLoadIdentity();                /* Reset The View */
slouken@5232
   368
gabomdq@7663
   369
    glTranslatef(-1.5f,0.0f,0.0f);        /* Move Left 1.5 Units */
slouken@7191
   370
gabomdq@7663
   371
    /* draw a triangle (in smooth coloring mode) */
gabomdq@7663
   372
    glBegin(GL_POLYGON);                /* start drawing a polygon */
gabomdq@7663
   373
    glColor3f(1.0f,0.0f,0.0f);            /* Set The Color To Red */
gabomdq@7663
   374
    glVertex3f( 0.0f, 1.0f, 0.0f);        /* Top */
gabomdq@7663
   375
    glColor3f(0.0f,1.0f,0.0f);            /* Set The Color To Green */
gabomdq@7663
   376
    glVertex3f( 1.0f,-1.0f, 0.0f);        /* Bottom Right */
gabomdq@7663
   377
    glColor3f(0.0f,0.0f,1.0f);            /* Set The Color To Blue */
gabomdq@7663
   378
    glVertex3f(-1.0f,-1.0f, 0.0f);        /* Bottom Left */
gabomdq@7663
   379
    glEnd();                    /* we're done with the polygon (smooth color interpolation) */
slouken@5232
   380
gabomdq@7663
   381
    glTranslatef(3.0f,0.0f,0.0f);         /* Move Right 3 Units */
slouken@5232
   382
gabomdq@7663
   383
    /* Enable blending */
slouken@5232
   384
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@5232
   385
    glEnable(GL_BLEND);
slouken@5232
   386
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
slouken@5232
   387
gabomdq@7663
   388
    /* draw a textured square (quadrilateral) */
slouken@5232
   389
    glEnable(GL_TEXTURE_2D);
slouken@5232
   390
    glBindTexture(GL_TEXTURE_2D, texture);
slouken@5232
   391
    glColor3f(1.0f,1.0f,1.0f);
slouken@5232
   392
    if (shaders_supported) {
slouken@5232
   393
        glUseProgramObjectARB(shaders[current_shader].program);
slouken@5232
   394
    }
slouken@5232
   395
gabomdq@7663
   396
    glBegin(GL_QUADS);                /* start drawing a polygon (4 sided) */
slouken@5232
   397
    glTexCoord2f(texcoord[MINX], texcoord[MINY]);
gabomdq@7663
   398
    glVertex3f(-1.0f, 1.0f, 0.0f);        /* Top Left */
slouken@5232
   399
    glTexCoord2f(texcoord[MAXX], texcoord[MINY]);
gabomdq@7663
   400
    glVertex3f( 1.0f, 1.0f, 0.0f);        /* Top Right */
slouken@5232
   401
    glTexCoord2f(texcoord[MAXX], texcoord[MAXY]);
gabomdq@7663
   402
    glVertex3f( 1.0f,-1.0f, 0.0f);        /* Bottom Right */
slouken@5232
   403
    glTexCoord2f(texcoord[MINX], texcoord[MAXY]);
gabomdq@7663
   404
    glVertex3f(-1.0f,-1.0f, 0.0f);        /* Bottom Left */
gabomdq@7663
   405
    glEnd();                    /* done with the polygon */
slouken@5232
   406
slouken@5232
   407
    if (shaders_supported) {
slouken@5232
   408
        glUseProgramObjectARB(0);
slouken@5232
   409
    }
slouken@5232
   410
    glDisable(GL_TEXTURE_2D);
slouken@5232
   411
gabomdq@7663
   412
    /* swap buffers to display, since we're double buffered. */
slouken@7323
   413
    SDL_GL_SwapWindow(window);
slouken@5232
   414
}
slouken@5232
   415
slouken@7191
   416
int main(int argc, char **argv)
slouken@7191
   417
{
slouken@5232
   418
    int done;
slouken@7323
   419
    SDL_Window *window;
slouken@5232
   420
    SDL_Surface *surface;
slouken@5232
   421
    GLuint texture;
slouken@5232
   422
    GLfloat texcoords[4];
slouken@5232
   423
philipp@9922
   424
    /* Enable standard application logging */
aschiffler@7639
   425
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
aschiffler@7639
   426
slouken@5232
   427
    /* Initialize SDL for video output */
slouken@5232
   428
    if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
aschiffler@7639
   429
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to initialize SDL: %s\n", SDL_GetError());
slouken@5232
   430
        exit(1);
slouken@5232
   431
    }
slouken@5232
   432
slouken@5232
   433
    /* Create a 640x480 OpenGL screen */
slouken@7323
   434
    window = SDL_CreateWindow( "Shader Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL );
slouken@7323
   435
    if ( !window ) {
aschiffler@7639
   436
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL window: %s\n", SDL_GetError());
slouken@5232
   437
        SDL_Quit();
slouken@5232
   438
        exit(2);
slouken@5232
   439
    }
slouken@5232
   440
slouken@7323
   441
    if ( !SDL_GL_CreateContext(window)) {
aschiffler@7639
   442
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL context: %s\n", SDL_GetError());
slouken@7323
   443
        SDL_Quit();
slouken@7323
   444
        exit(2);
slouken@7323
   445
    }
slouken@5232
   446
slouken@5232
   447
    surface = SDL_LoadBMP("icon.bmp");
slouken@5232
   448
    if ( ! surface ) {
aschiffler@7639
   449
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError());
slouken@5232
   450
        SDL_Quit();
slouken@5232
   451
        exit(3);
slouken@5232
   452
    }
slouken@5232
   453
    texture = SDL_GL_LoadTexture(surface, texcoords);
slouken@5232
   454
    SDL_FreeSurface(surface);
slouken@5232
   455
slouken@5232
   456
    /* Loop, drawing and checking events */
slouken@5232
   457
    InitGL(640, 480);
slouken@5232
   458
    if (InitShaders()) {
aschiffler@7639
   459
        SDL_Log("Shaders supported, press SPACE to cycle them.\n");
slouken@5232
   460
    } else {
aschiffler@7639
   461
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shaders not supported!\n");
slouken@5232
   462
    }
slouken@5232
   463
    done = 0;
slouken@5232
   464
    while ( ! done ) {
slouken@7323
   465
        DrawGLScene(window, texture, texcoords);
slouken@5232
   466
slouken@5232
   467
        /* This could go in a separate function */
slouken@5232
   468
        { SDL_Event event;
slouken@5232
   469
            while ( SDL_PollEvent(&event) ) {
slouken@5232
   470
                if ( event.type == SDL_QUIT ) {
slouken@5232
   471
                    done = 1;
slouken@5232
   472
                }
slouken@5232
   473
                if ( event.type == SDL_KEYDOWN ) {
slouken@5232
   474
                    if ( event.key.keysym.sym == SDLK_SPACE ) {
slouken@5232
   475
                        current_shader = (current_shader + 1) % NUM_SHADERS;
slouken@5232
   476
                    }
slouken@5232
   477
                    if ( event.key.keysym.sym == SDLK_ESCAPE ) {
slouken@5232
   478
                        done = 1;
slouken@5232
   479
                    }
slouken@5232
   480
                }
slouken@5232
   481
            }
slouken@5232
   482
        }
slouken@5232
   483
    }
slouken@5232
   484
    QuitShaders();
slouken@5232
   485
    SDL_Quit();
slouken@5232
   486
    return 1;
slouken@5232
   487
}
slouken@5232
   488
slouken@5232
   489
#else /* HAVE_OPENGL */
slouken@5232
   490
slouken@5232
   491
int
slouken@5232
   492
main(int argc, char *argv[])
slouken@5232
   493
{
aschiffler@7639
   494
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No OpenGL support on this system\n");
slouken@5232
   495
    return 1;
slouken@5232
   496
}
slouken@5232
   497
slouken@5232
   498
#endif /* HAVE_OPENGL */
slouken@5236
   499
slouken@5236
   500
/* vi: set ts=4 sw=4 expandtab: */