/* * Create shader, load in source, compile, dump debug as necessary. * * shader: Pointer to return created shader ID. * source: Passed-in shader source code. * shader_type: Passed to GL, e.g. GL_VERTEX_SHADER. */ void process_shader(GLuint *shader, const char * source, GLint shader_type) { GLint status = GL_FALSE; const char *shaders[1] = { NULL }; char buffer[1024]; GLsizei length; /* Create shader and load into GL. */ *shader = GL_CHECK(ctx.glCreateShader(shader_type)); shaders[0] = source; GL_CHECK(ctx.glShaderSource(*shader, 1, shaders, NULL)); /* Clean up shader source. */ shaders[0] = NULL; /* Try compiling the shader. */ GL_CHECK(ctx.glCompileShader(*shader)); GL_CHECK(ctx.glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); /* Dump debug info (source and log) if compilation failed. */ if(status != GL_TRUE) { ctx.glGetProgramInfoLog(*shader, sizeof(buffer), &length, &buffer[0]); buffer[length] = '\0'; SDL_Log("Shader compilation failed: %s", buffer);fflush(stderr); quit(-1); } }
/* * Create shader, load in source, compile, dump debug as necessary. * * shader: Pointer to return created shader ID. * source: Passed-in shader source code. * shader_type: Passed to GL, e.g. GL_VERTEX_SHADER. */ void process_shader(GLuint *shader, const char * source, GLint shader_type) { GLint status = GL_FALSE; const char *shaders[1] = { NULL }; /* Create shader and load into GL. */ *shader = GL_CHECK(ctx.glCreateShader(shader_type)); shaders[0] = source; GL_CHECK(ctx.glShaderSource(*shader, 1, shaders, NULL)); /* Clean up shader source. */ shaders[0] = NULL; /* Try compiling the shader. */ GL_CHECK(ctx.glCompileShader(*shader)); GL_CHECK(ctx.glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); // Dump debug info (source and log) if compilation failed. if(status != GL_TRUE) { SDL_Log("Shader compilation failed"); quit(-1); } }
void loop() { SDL_Event event; int i; int status; /* Check for events */ ++frames; while (SDL_PollEvent(&event) && !done) { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: for (i = 0; i < state->num_windows; ++i) { if (event.window.windowID == SDL_GetWindowID(state->windows[i])) { int w, h; status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); break; } /* Change view port to the new window dimensions */ SDL_GL_GetDrawableSize(state->windows[i], &w, &h); ctx.glViewport(0, 0, w, h); state->window_w = event.window.data1; state->window_h = event.window.data2; /* Update window content */ Render(event.window.data1, event.window.data2, &datas[i]); SDL_GL_SwapWindow(state->windows[i]); break; } } break; } } SDLTest_CommonEvent(state, &event, &done); } if (!done) { for (i = 0; i < state->num_windows; ++i) { status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); /* Continue for next window */ continue; } Render(state->window_w, state->window_h, &datas[i]); SDL_GL_SwapWindow(state->windows[i]); } } #ifdef __EMSCRIPTEN__ else { emscripten_cancel_main_loop(); } #endif }
static void Render(unsigned int width, unsigned int height, shader_data* data) { float matrix_rotate[16], matrix_modelview[16], matrix_perspective[16], matrix_mvp[16]; /* * Do some rotation with Euler angles. It is not a fixed axis as * quaterions would be, but the effect is cool. */ rotate_matrix((float)data->angle_x, 1.0f, 0.0f, 0.0f, matrix_modelview); rotate_matrix((float)data->angle_y, 0.0f, 1.0f, 0.0f, matrix_rotate); multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview); rotate_matrix((float)data->angle_z, 0.0f, 1.0f, 0.0f, matrix_rotate); multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview); /* Pull the camera back from the cube */ matrix_modelview[14] -= 2.5; perspective_matrix(45.0f, (float)width/height, 0.01f, 100.0f, matrix_perspective); multiply_matrix(matrix_perspective, matrix_modelview, matrix_mvp); GL_CHECK(ctx.glUniformMatrix4fv(data->attr_mvp, 1, GL_FALSE, matrix_mvp)); data->angle_x += 3; data->angle_y += 2; data->angle_z += 1; if(data->angle_x >= 360) data->angle_x -= 360; if(data->angle_x < 0) data->angle_x += 360; if(data->angle_y >= 360) data->angle_y -= 360; if(data->angle_y < 0) data->angle_y += 360; if(data->angle_z >= 360) data->angle_z -= 360; if(data->angle_z < 0) data->angle_z += 360; GL_CHECK(ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36)); }
int main(int argc, char *argv[]) { int fsaa, accel; int value; int i; SDL_DisplayMode mode; Uint32 then, now; int status; shader_data *data; /* Initialize parameters */ fsaa = 0; accel = 0; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); if (!state) { return 1; } for (i = 1; i < argc;) { int consumed; consumed = SDLTest_CommonArg(state, i); if (consumed == 0) { if (SDL_strcasecmp(argv[i], "--fsaa") == 0) { ++fsaa; consumed = 1; } else if (SDL_strcasecmp(argv[i], "--accel") == 0) { ++accel; consumed = 1; } else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) { i++; if (!argv[i]) { consumed = -1; } else { depth = SDL_atoi(argv[i]); consumed = 1; } } else { consumed = -1; } } if (consumed < 0) { SDL_Log ("Usage: %s %s [--fsaa] [--accel] [--zdepth %%d]\n", argv[0], SDLTest_CommonUsage(state)); quit(1); } i += consumed; } /* Set OpenGL parameters */ state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS; state->gl_red_size = 5; state->gl_green_size = 5; state->gl_blue_size = 5; state->gl_depth_size = depth; state->gl_major_version = 2; state->gl_minor_version = 0; state->gl_profile_mask = SDL_GL_CONTEXT_PROFILE_ES; if (fsaa) { state->gl_multisamplebuffers=1; state->gl_multisamplesamples=fsaa; } if (accel) { state->gl_accelerated=1; } if (!SDLTest_CommonInit(state)) { quit(2); return 0; } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(context)); if (context == NULL) { SDL_Log("Out of memory!\n"); quit(2); } /* Create OpenGL ES contexts */ for (i = 0; i < state->num_windows; i++) { context[i] = SDL_GL_CreateContext(state->windows[i]); if (!context[i]) { SDL_Log("SDL_GL_CreateContext(): %s\n", SDL_GetError()); quit(2); } } /* Important: call this *after* creating the context */ if (LoadContext(&ctx) < 0) { SDL_Log("Could not load GLES2 functions\n"); quit(2); return 0; } /* from here on out, it should be ok to call gles 2.0 routines */ if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); } SDL_Log("first call address is %llx data is %lx\n",(long long)(&glGetString),GL_VENDOR); const char *test = ctx.glGetString(GL_VENDOR); if (test) { SDL_Log("we got %s\n",test); } else { SDL_Log("we got a null.\n"); quit(2); } SDL_Log("try again call address is %lx\n",(long long)(&glGetString)); SDL_Log("first ctx address is %llx data is %lx ind %llx\n",(long long)(ctx.glGetString),GL_VENDOR,((long long *)(ctx.glGetString))[0] ); {const char *test = glGetString(GL_VENDOR); if (test) { SDL_Log("we got %s\n",test); } else { SDL_Log("we got a null.\n"); quit(2); } } SDL_GetCurrentDisplayMode(0, &mode); SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format)); SDL_Log("\n"); SDL_Log("Vendor : %s\n", glGetString(GL_VENDOR)); SDL_Log("Renderer : %s\n", glGetString(GL_RENDERER)); SDL_Log("Version : %s\n", glGetString(GL_VERSION)); SDL_Log("Extensions : %s\n", glGetString(GL_EXTENSIONS)); SDL_Log("\n"); status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); if (!status) { SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); } else { SDL_Log( "Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); if (!status) { SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); } else { SDL_Log( "Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); if (!status) { SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); } else { SDL_Log( "Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); if (!status) { SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", depth, value); } else { SDL_Log( "Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError()); } if (fsaa) { status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); if (!status) { SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); } else { SDL_Log( "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); if (!status) { SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value); } else { SDL_Log( "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n", SDL_GetError()); } } if (accel) { status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); if (!status) { SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); } else { SDL_Log( "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n", SDL_GetError()); } } datas = (shader_data *)SDL_calloc(state->num_windows, sizeof(shader_data)); /* Set rendering settings for each context */ for (i = 0; i < state->num_windows; ++i) { int w, h; status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); /* Continue for next window */ continue; } SDL_GL_GetDrawableSize(state->windows[i], &w, &h); glViewport(0, 0, w, h); data = &datas[i]; data->angle_x = 0; data->angle_y = 0; data->angle_z = 0; /* Shader Initialization */ process_shader(&data->shader_vert, _shader_vert_src, GL_VERTEX_SHADER); process_shader(&data->shader_frag, _shader_frag_src, GL_FRAGMENT_SHADER); /* Create shader_program (ready to attach shaders) */ data->shader_program = GL_CHECK(glCreateProgram()); /* Attach shaders and link shader_program */ GL_CHECK(glAttachShader(data->shader_program, data->shader_vert)); GL_CHECK(glAttachShader(data->shader_program, data->shader_frag)); GL_CHECK(glLinkProgram(data->shader_program)); /* Get attribute locations of non-fixed attributes like color and texture coordinates. */ data->attr_position = GL_CHECK(glGetAttribLocation(data->shader_program, "av4position")); data->attr_color = GL_CHECK(glGetAttribLocation(data->shader_program, "av3color")); /* Get uniform locations */ data->attr_mvp = GL_CHECK(glGetUniformLocation(data->shader_program, "mvp")); GL_CHECK(glUseProgram(data->shader_program)); /* Enable attributes for position, color and texture coordinates etc. */ GL_CHECK(glEnableVertexAttribArray(data->attr_position)); GL_CHECK(glEnableVertexAttribArray(data->attr_color)); /* Populate attributes for position, color and texture coordinates etc. */ GL_CHECK(glVertexAttribPointer(data->attr_position, 3, GL_FLOAT, GL_FALSE, 0, _vertices)); GL_CHECK(glVertexAttribPointer(data->attr_color, 3, GL_FLOAT, GL_FALSE, 0, _colors)); GL_CHECK(glEnable(GL_CULL_FACE)); GL_CHECK(glEnable(GL_DEPTH_TEST)); } /* Main render loop */ frames = 0; then = SDL_GetTicks(); done = 0; #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(loop, 0, 1); #else while (!done) { loop(); } #endif /* Print out some timing information */ now = SDL_GetTicks(); if (now > then) { SDL_Log("%2.2f frames per second\n", ((double) frames * 1000) / (now - then)); } #if !defined(__ANDROID__) && !defined(__NACL__) quit(0); #endif return 0; }