int main(int argc, char **argv) { struct fd_state *state; struct fd_surface *surface, *lolstex1, *lolstex2; struct fd_program *cat_program, *tex_program; struct fd_bo *position_vbo, *normal_vbo; const char *cat_vertex_shader_asm = "@varying(R0) vertex_normal \n" "@varying(R1) vertex_position \n" "@attribute(R1) normal \n" "@attribute(R2) position \n" "@uniform(C0-C3) ModelViewMatrix \n" "@uniform(C4-C7) ModelViewProjectionMatrix \n" "@uniform(C8-C10) NormalMatrix \n" "@const(C11) 1.000000, 0.000000, 0.000000, 0.000000 \n" "EXEC \n" " FETCH: VERTEX R1.xyz_ = R0.x FMT_32_32_32_FLOAT SIGNED STRIDE(12) CONST(20, 0)\n" " FETCH: VERTEX R2.xyz_ = R0.x FMT_32_32_32_FLOAT SIGNED STRIDE(12) CONST(20, 1)\n" " (S)ALU: MULADDv R0 = C7, R2.zzzz, C6 \n" " ALU: MULADDv R0 = R0, R2.yyyy, C5 \n" "ALLOC POSITION SIZE(0x0) \n" "EXEC \n" " ALU: MULADDv export62 = R0, R2.xxxx, C4 ; gl_Position \n" " ALU: MULv R0.xyz_ = R1.zzzw, C10 \n" " ALU: MULADDv R0.xyz_ = R0, R1.yyyw, C9 \n" " ALU: MULADDv R0.xyz_ = R0, R1.xxxw, C8 \n" " ALU: DOT3v R1.x___ = R0, R0 \n" " ALU: MULADDv R3 = C3, R2.zzzz, C2 \n" "EXEC \n" " ALU: MULADDv R3 = R3, R2.yyyy, C1 \n" " ALU: MAXv R0.____ = R0, R0 \n" " RECIPSQ_IEEE R0.___w = R1.xyzx \n" "ALLOC PARAM/PIXEL SIZE(0x1) \n" "EXEC_END \n" " ALU: MULADDv export1 = R3, R2.xxxx, C0 \n" " ALU: MULv export0.xyz_ = R0, R0.wwww \n"; const char *cat_fragment_shader_asm = /* precision mediump float; const vec4 MaterialDiffuse = vec4(0.000000, 0.000000, 1.000000, 1.000000); const vec4 LightColor0 = vec4(0.800000, 0.800000, 0.800000, 1.000000); const vec4 light_position = vec4(0.000000, 1.000000, 0.000000, 1.000000); varying vec3 vertex_normal; varying vec4 vertex_position; void main(void) { const vec4 diffuse_light_color = LightColor0; const vec4 lightAmbient = vec4(0.1, 0.1, 0.1, 1.0); const vec4 lightSpecular = vec4(0.8, 0.8, 0.8, 1.0); const vec4 matAmbient = vec4(0.2, 0.2, 0.2, 1.0); const vec4 matSpecular = vec4(1.0, 1.0, 1.0, 1.0); const float matShininess = 100.0; // C4.x vec3 eye_direction = normalize(-vertex_position.xyz); vec3 light_direction = normalize(light_position.xyz/light_position.w - vertex_position.xyz/vertex_position.w); vec3 normalized_normal = normalize(vertex_normal); // reflect(i,n) -> i - 2 * dot(n,i) * n vec3 reflection = reflect(-light_direction, normalized_normal); float specularTerm = pow(max(0.0, dot(reflection, eye_direction)), matShininess); float diffuseTerm = max(0.0, dot(normalized_normal, light_direction)); vec4 specular = (lightSpecular * matSpecular); vec4 ambient = (lightAmbient * matAmbient); vec4 diffuse = (diffuse_light_color * MaterialDiffuse); vec4 result = (specular * specularTerm) + ambient + (diffuse * diffuseTerm); gl_FragColor = result; } */ "@varying(R0) vertex_normal \n" "@varying(R1) vertex_position \n" "@const(C0) 0.000000, 1.000000, 0.000000, 0.000000 \n" "@const(C1) 0.800000, 0.800000, 0.800000, 1.000000 \n" "@const(C2) 0.020000, 0.020000, 0.020000, 1.000000 \n" "@const(C3) 0.000000, 0.000000, 0.800000, 1.000000 \n" "@const(C4) 100.000000, 0.000000, 0.000000, 0.000000 \n" "EXEC \n" " (S)ALU: DOT3v R2.x___ = R0, R0 ; normalize(vertex_normal) \n" " RECIP_IEEE R3.x___ = R1 ; 1/vertex_position.x ? R1.wyzw? \n" " ALU: MULADDv R3.xyz_ = C0.xyxw, -R1, R3.xxxw ; light_position.xyz/1.0 - \n" " ; vertex_position.xyz/vertex_position.w \n" " ALU: DOT3v R2.x___ = R3, R3 ; normalize(light_position...) \n" " RECIPSQ_IEEE R0.___w = R2.xyzx ; normalize(vertex_normal) \n" "; here the RSQ sees the R2 value written in first instruction, rather than \n" "; the R2 dst being calculated as part of the same VLIW instruction \n" " ALU: MULv R0.xyz_ = R0, R0.wwww ; normalized_normal = normalize(vertex_normal) \n" " RECIPSQ_IEEE R0.___w = R2.xyzx ; normalize(light_position...) \n" " ALU: MULv R2.xyz_ = R3, R0.wwww ; light_direction = normalize(light_position...) \n" " ALU: DOT3v R3.x___ = -R1, -R1 ; normalize(-vertex_position.xyz) \n" "EXEC \n" "; reflect(i,n) -> i - 2 * dot(n,i) * n \n" " ALU: DOT3v R3.x___ = -R2, R0 ; reflect(-light_direction, normalized_normal) \n" " RECIPSQ_IEEE R0.___w = R3.xyzx ; normalize(-vertex_position.xyz); \n" " ALU: MULv R1.xyz_ = -R1, R0.wwww ; eye_direction = normalize(-vertex_position.xyz) \n" " ADDs R3.x___ = R3.xyzx ; 2 * dot(n, i) \n" " ALU: MULADDv R3.xyz_ = -R2, R0, -R3.xxxw ; reflect(..) -> i + (n * (2 * dot(n, i)) \n" " ALU: DOT3v R1.x___ = R1, R3 ; dot(reflection, eye_direction) \n" " ALU: MAXv R1.x___ = R1, C0 ; max(0.0, dot(reflection, eye_direction) \n" " ALU: DOT3v R0.x___ = R2, R0 ; dot(normalized_normal, light_direction) \n" " LOG_CLAMP R0.___w = R1.xyzx ; pow(max(0.0, dot(...)), matShininess) \n" "EXEC \n" " ALU: MAXv R0.x___ = R0, C0 ; diffuseTerm = max(0.0, dot(...)) \n" " MUL_CONST_0 R0.___w = C4.wyzx ; specularTerm = pow(..., matShininess) \n" " ALU: MAXv R0.____ = R0, R0 \n" " EXP_IEEE R1.x___ = R0 ; specularTerm = pow(..) \n" "; C2 is ambient = (lightAmbient * matAmbient) = vec4(0.1,0.1,0.1,1.0) * vec4(0.2,0.2,0.2,1.0) \n" "; C1 is specular = (lightSpecular * matSpecular) = vec4(0.8,0.8,0.8,1.0) * vec4(1.0,1.0,1.0,1.0) \n" " ALU: MULADDv R1.x__w = C2, R1.xyzx, C1 ; ambient + (specularTerm * specular) \n" "ALLOC PARAM/PIXEL SIZE(0x0) \n" "EXEC_END ADDR(0x12) CNT(0x1) \n" " ALU: MULADDv export0 = R1.xxxw, R0.xxxx, C3.xxzw ; gl_FragColor \n" "NOP \n"; static const GLfloat texcoords[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; static const GLfloat tex1_vertices[] = { -0.95, +0.45, -1.0, +0.45, +0.45, -1.0, -0.95, +0.95, -1.0, +0.45, +0.95, -1.0 }; static const GLfloat tex2_vertices[] = { -0.45, -0.95, -1.0, +0.95, -0.95, -1.0, -0.45, -0.45, -1.0, +0.95, -0.45, -1.0 }; const char *tex_vertex_shader_asm = "@attribute(R1) aPosition \n" "@attribute(R2) aTexCoord \n" "@varying(R0) vTexCoord \n" "EXEC \n" " FETCH: VERTEX R2.xy11 = R0.x FMT_32_32_FLOAT SIGNED \n" " STRIDE(8) CONST(20, 1) \n" " (S)FETCH: VERTEX R1.xyz1 = R0.x FMT_32_32_32_FLOAT SIGNED \n" " STRIDE(12) CONST(20, 0) \n" "ALLOC POSITION SIZE(0x0) \n" "EXEC \n" " ALU: MAXv export62 = R1, R1 ; gl_Position \n" "ALLOC PARAM/PIXEL SIZE(0x0) \n" "EXEC_END \n" " ALU: MAXv export0 = R2, R2 ; vTexCoord \n" "NOP \n"; const char *tex_fragment_shader_asm = "@varying(R0) vTexCoord \n" "@sampler(0) uTexture \n" "EXEC \n" " (S)FETCH: SAMPLE R0.xyzw = R0.xyx CONST(0) \n" "ALLOC PARAM/PIXEL SIZE(0x0) \n" "EXEC_END \n" " ALU: MAXv export0 = R0, R0 ; gl_FragColor \n" "NOP \n"; uint32_t width = 0, height = 0; int i, n = 1; if (argc == 2) n = atoi(argv[1]); DEBUG_MSG("----------------------------------------------------------------"); RD_START("fd-cat", ""); state = fd_init(); if (!state) return -1; surface = fd_surface_screen(state, &width, &height); if (!surface) return -1; /* load textures: */ lolstex1 = fd_surface_new_fmt(state, lolstex1_image.width, lolstex1_image.height, COLORX_8_8_8_8); fd_surface_upload(lolstex1, lolstex1_image.pixel_data); lolstex2 = fd_surface_new_fmt(state, lolstex2_image.width, lolstex2_image.height, COLORX_8_8_8_8); fd_surface_upload(lolstex2, lolstex2_image.pixel_data); fd_enable(state, GL_CULL_FACE); fd_depth_func(state, GL_LEQUAL); fd_enable(state, GL_DEPTH_TEST); fd_tex_param(state, GL_TEXTURE_MAG_FILTER, GL_LINEAR); fd_tex_param(state, GL_TEXTURE_MIN_FILTER, GL_LINEAR); fd_blend_func(state, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* this needs to come after enabling depth test as enabling depth test * effects bin sizes: */ fd_make_current(state, surface); /* construct the two shader programs: */ cat_program = fd_program_new(); fd_program_attach_asm(cat_program, FD_SHADER_VERTEX, cat_vertex_shader_asm); fd_program_attach_asm(cat_program, FD_SHADER_FRAGMENT, cat_fragment_shader_asm); tex_program = fd_program_new(); fd_program_attach_asm(tex_program, FD_SHADER_VERTEX, tex_vertex_shader_asm); fd_program_attach_asm(tex_program, FD_SHADER_FRAGMENT, tex_fragment_shader_asm); fd_link(state); position_vbo = fd_attribute_bo_new(state, cat_position_sz, cat_position); normal_vbo = fd_attribute_bo_new(state, cat_normal_sz, cat_normal); for (i = 0; i < n; i++) { GLfloat aspect = (GLfloat)height / (GLfloat)width; ESMatrix modelview; ESMatrix projection; ESMatrix modelviewprojection; float normal[9]; float scale = 1.8; esMatrixLoadIdentity(&modelview); esTranslate(&modelview, 0.0f, 0.0f, -8.0f); esRotate(&modelview, 45.0f - (0.5f * i), 0.0f, 1.0f, 0.0f); esMatrixLoadIdentity(&projection); esFrustum(&projection, -scale, +scale, -scale * aspect, +scale * aspect, 5.5f, 10.0f); esMatrixLoadIdentity(&modelviewprojection); esMatrixMultiply(&modelviewprojection, &modelview, &projection); normal[0] = modelview.m[0][0]; normal[1] = modelview.m[0][1]; normal[2] = modelview.m[0][2]; normal[3] = modelview.m[1][0]; normal[4] = modelview.m[1][1]; normal[5] = modelview.m[1][2]; normal[6] = modelview.m[2][0]; normal[7] = modelview.m[2][1]; normal[8] = modelview.m[2][2]; fd_clear_color(state, 0xff000000); fd_clear(state, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); fd_attribute_bo(state, "normal", normal_vbo); fd_attribute_bo(state, "position", position_vbo); fd_uniform_attach(state, "ModelViewMatrix", 4, 4, &modelview.m[0][0]); fd_uniform_attach(state, "ModelViewProjectionMatrix", 4, 4, &modelviewprojection.m[0][0]); fd_uniform_attach(state, "NormalMatrix", 3, 3, normal); /* draw cat: */ fd_disable(state, GL_BLEND); fd_set_program(state, cat_program); fd_draw_arrays(state, GL_TRIANGLES, 0, cat_vertices); /* setup to draw text (common to tex1 and tex2): */ fd_enable(state, GL_BLEND); fd_set_program(state, tex_program); fd_attribute_pointer(state, "aTexCoord", 2, 4, texcoords); /* draw tex1: */ fd_set_texture(state, "uTexture", lolstex1); fd_attribute_pointer(state, "aPosition", 3, 4, tex1_vertices); fd_draw_arrays(state, GL_TRIANGLE_STRIP, 0, 4); /* draw tex2: */ fd_set_texture(state, "uTexture", lolstex2); fd_attribute_pointer(state, "aPosition", 3, 4, tex2_vertices); fd_draw_arrays(state, GL_TRIANGLE_STRIP, 0, 4); fd_swap_buffers(state); } fd_flush(state); fd_dump_bmp(surface, "lolscat.bmp"); fd_fini(state); RD_END(); return 0; }
int main(int argc, char **argv) { struct fd_state *state; struct fd_surface *surface; int width, height; static const GLfloat vertices[] = { -0.75f, +0.25f, +0.50f, // Quad #0 -0.25f, +0.25f, +0.50f, -0.25f, +0.75f, +0.50f, -0.75f, +0.75f, +0.50f, +0.25f, +0.25f, +0.90f, // Quad #1 +0.75f, +0.25f, +0.90f, +0.75f, +0.75f, +0.90f, +0.25f, +0.75f, +0.90f, -0.75f, -0.75f, +0.50f, // Quad #2 -0.25f, -0.75f, +0.50f, -0.25f, -0.25f, +0.50f, -0.75f, -0.25f, +0.50f, +0.25f, -0.75f, +0.50f, // Quad #3 +0.75f, -0.75f, +0.50f, +0.75f, -0.25f, +0.50f, +0.25f, -0.25f, +0.50f, -1.00f, -1.00f, +0.00f, // Big Quad +1.00f, -1.00f, +0.00f, +1.00f, +1.00f, +0.00f, -1.00f, +1.00f, +0.00f, }; static const GLubyte indices[][6] = { { 0, 1, 2, 0, 2, 3 }, // Quad #0 { 4, 5, 6, 4, 6, 7 }, // Quad #1 { 8, 9, 10, 8, 10, 11 }, // Quad #2 { 12, 13, 14, 12, 14, 15 }, // Quad #3 { 16, 17, 18, 16, 18, 19 }, // Big Quad }; #define NumTests 4 static const GLfloat colors[NumTests][4] = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 0.0f }, }; #if 0 const char *vertex_shader_source = "attribute vec4 aPosition; \n" " \n" "void main() \n" "{ \n" " gl_Position = aPosition; \n" "} \n"; const char *fragment_shader_source = "precision highp float; \n" "uniform vec4 uColor; \n" " \n" "void main() \n" "{ \n" " gl_FragColor = uColor; \n" "} \n"; #else const char *vertex_shader_asm = "@attribute(R1) aPosition \n" "EXEC \n" " (S)FETCH: VERTEX R1.xyz1 = R0.x FMT_32_32_32_FLOAT SIGNED \n" " STRIDE(12) CONST(20, 0) \n" "ALLOC POSITION SIZE(0x0) \n" "EXEC \n" " ALU: MAXv export62 = R1, R1 ; gl_Position \n" "ALLOC PARAM/PIXEL SIZE(0x0) \n" "EXEC_END \n" "NOP \n"; const char *fragment_shader_asm = "@uniform(C0) uColor \n" "ALLOC PARAM/PIXEL SIZE(0x0) \n" "EXEC_END \n" " ALU: MAXv export0 = C0, C0 ; gl_FragColor \n"; #endif GLint numStencilBits; GLuint stencilValues[NumTests] = { 0x7, // Result of test 0 0x0, // Result of test 1 0x2, // Result of test 2 0xff // Result of test 3. We need to fill this value in a run-time }; int i; DEBUG_MSG("----------------------------------------------------------------"); RD_START("fd-stencil", ""); state = fd_init(); if (!state) return -1; surface = fd_surface_screen(state, &width, &height); if (!surface) return -1; fd_enable(state, GL_DEPTH_TEST); fd_enable(state, GL_STENCIL_TEST); /* this needs to come after enabling depth/stencil test as these * effect bin sizes: */ fd_make_current(state, surface); fd_vertex_shader_attach_asm(state, vertex_shader_asm); fd_fragment_shader_attach_asm(state, fragment_shader_asm); fd_link(state); fd_clear_color(state, 0x00000000); fd_clear_stencil(state, 0x1); fd_clear_depth(state, 0.75); // Clear the color, depth, and stencil buffers. At this // point, the stencil buffer will be 0x1 for all pixels fd_clear(state, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); fd_attribute_pointer(state, "aPosition", 3, 20, vertices); fd_uniform_attach(state, "uColor", 4, 1, (GLfloat[]){ 0.0, 0.0, 0.0, 0.0, }); // Test 0: // // Initialize upper-left region. In this case, the // stencil-buffer values will be replaced because the // stencil test for the rendered pixels will fail the // stencil test, which is // // ref mask stencil mask // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 ) // // The value in the stencil buffer for these pixels will // be 0x7. // fd_stencil_func(state, GL_LESS, 0x7, 0x3); fd_stencil_op(state, GL_REPLACE, GL_DECR, GL_DECR); fd_draw_elements(state, GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0]); // Test 1: // // Initialize the upper-right region. Here, we'll decrement // the stencil-buffer values where the stencil test passes // but the depth test fails. The stencil test is // // ref mask stencil mask // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 ) // // but where the geometry fails the depth test. The // stencil values for these pixels will be 0x0. // fd_stencil_func(state, GL_GREATER, 0x3, 0x3); fd_stencil_op(state, GL_KEEP, GL_DECR, GL_KEEP); fd_draw_elements(state, GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1]); // Test 2: // // Initialize the lower-left region. Here we'll increment // (with saturation) the stencil value where both the // stencil and depth tests pass. The stencil test for // these pixels will be // // ref mask stencil mask // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 ) // // The stencil values for these pixels will be 0x2. // fd_stencil_func(state, GL_EQUAL, 0x1, 0x3); fd_stencil_op(state, GL_KEEP, GL_INCR, GL_INCR); fd_draw_elements(state, GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2]); // Test 3: // // Finally, initialize the lower-right region. We'll invert // the stencil value where the stencil tests fails. The // stencil test for these pixels will be // // ref mask stencil mask // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 ) // // The stencil value here will be set to ~((2^s-1) & 0x1), // (with the 0x1 being from the stencil clear value), // where 's' is the number of bits in the stencil buffer // fd_stencil_func(state, GL_EQUAL, 0x2, 0x1); fd_stencil_op(state, GL_INVERT, GL_KEEP, GL_KEEP); fd_draw_elements(state, GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3]); // Since we don't know at compile time how many stencil bits are present, // we'll query, and update the value correct value in the // stencilValues arrays for the fourth tests. We'll use this value // later in rendering. numStencilBits = 8; stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff; // Use the stencil buffer for controlling where rendering will // occur. We disable writing to the stencil buffer so we // can test against them without modifying the values we // generated. fd_stencil_mask(state, 0x0); for (i = 0; i < NumTests; i++) { fd_stencil_func(state, GL_EQUAL, stencilValues[i], 0xff); fd_uniform_attach(state, "uColor", 4, 1, colors[i]); fd_draw_elements(state, GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4]); } fd_swap_buffers(state); fd_flush(state); fd_dump_bmp(surface, "stencil.bmp"); fd_fini(state); RD_END(); return 0; }