1// Copyright (C) 2009 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma version(1)
16
17#pragma rs java_package_name(com.example.android.rs.miscsamples)
18
19#include "rs_graphics.rsh"
20#include "shader_def.rsh"
21
22const int gMaxModes = 11;
23
24rs_program_vertex gProgVertex;
25rs_program_fragment gProgFragmentColor;
26rs_program_fragment gProgFragmentTexture;
27
28rs_program_store gProgStoreBlendNoneDepth;
29rs_program_store gProgStoreBlendNone;
30rs_program_store gProgStoreBlendAlpha;
31rs_program_store gProgStoreBlendAdd;
32
33rs_allocation gTexOpaque;
34rs_allocation gTexTorus;
35rs_allocation gTexTransparent;
36rs_allocation gTexChecker;
37rs_allocation gTexCube;
38
39rs_mesh gMbyNMesh;
40rs_mesh gTorusMesh;
41
42rs_font gFontSans;
43rs_font gFontSerif;
44rs_font gFontSerifBold;
45rs_font gFontSerifItalic;
46rs_font gFontSerifBoldItalic;
47rs_font gFontMono;
48rs_allocation gTextAlloc;
49
50int gDisplayMode;
51
52rs_sampler gLinearClamp;
53rs_sampler gLinearWrap;
54rs_sampler gMipLinearWrap;
55rs_sampler gMipLinearAniso8;
56rs_sampler gMipLinearAniso15;
57rs_sampler gNearestClamp;
58
59rs_program_raster gCullBack;
60rs_program_raster gCullFront;
61rs_program_raster gCullNone;
62
63// Custom vertex shader compunents
64VertexShaderConstants *gVSConstants;
65VertexShaderConstants2 *gVSConstants2;
66FragentShaderConstants *gFSConstants;
67FragentShaderConstants2 *gFSConstants2;
68// Export these out to easily set the inputs to shader
69VertexShaderInputs *gVSInputs;
70// Custom shaders we use for lighting
71rs_program_vertex gProgVertexCustom;
72rs_program_fragment gProgFragmentCustom;
73rs_program_vertex gProgVertexCustom2;
74rs_program_fragment gProgFragmentCustom2;
75rs_program_vertex gProgVertexCube;
76rs_program_fragment gProgFragmentCube;
77rs_program_fragment gProgFragmentMultitex;
78
79float gDt = 0;
80
81void init() {
82}
83
84static void displayFontSamples() {
85    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
86    int yPos = 100;
87    rsgBindFont(gFontSans);
88    rsgDrawText("Sans font sample", 30, yPos);
89    yPos += 30;
90    rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
91    rsgBindFont(gFontSerif);
92    rsgDrawText("Serif font sample", 30, yPos);
93    yPos += 30;
94    rsgFontColor(0.7f, 0.7f, 0.7f, 1.0f);
95    rsgBindFont(gFontSerifBold);
96    rsgDrawText("Serif Bold font sample", 30, yPos);
97    yPos += 30;
98    rsgFontColor(0.5f, 0.5f, 0.9f, 1.0f);
99    rsgBindFont(gFontSerifItalic);
100    rsgDrawText("Serif Italic font sample", 30, yPos);
101    yPos += 30;
102    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
103    rsgBindFont(gFontSerifBoldItalic);
104    rsgDrawText("Serif Bold Italic font sample", 30, yPos);
105    yPos += 30;
106    rsgBindFont(gFontMono);
107    rsgDrawText("Monospace font sample", 30, yPos);
108    yPos += 50;
109
110    // Now use text metrics to center the text
111    uint width = rsgGetWidth();
112    uint height = rsgGetHeight();
113    int left = 0, right = 0, top = 0, bottom = 0;
114
115    rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
116    rsgBindFont(gFontSerifBoldItalic);
117
118    rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom);
119    int centeredPos = width / 2 - (right - left) / 2;
120    rsgDrawText(gTextAlloc, centeredPos, yPos);
121    yPos += 30;
122
123    const char* text = "Centered Text Sample";
124    rsgMeasureText(text, &left, &right, &top, &bottom);
125    centeredPos = width / 2 - (right - left) / 2;
126    rsgDrawText(text, centeredPos, yPos);
127    yPos += 30;
128
129    rsgBindFont(gFontSans);
130    text = "More Centered Text Samples";
131    rsgMeasureText(text, &left, &right, &top, &bottom);
132    centeredPos = width / 2 - (right - left) / 2;
133    rsgDrawText(text, centeredPos, yPos);
134    yPos += 30;
135
136    // Now draw bottom and top right aligned text
137    text = "Top-right aligned text";
138    rsgMeasureText(text, &left, &right, &top, &bottom);
139    rsgDrawText(text, width - right, top);
140
141    text = "Top-left";
142    rsgMeasureText(text, &left, &right, &top, &bottom);
143    rsgDrawText(text, -left, top);
144
145    text = "Bottom-right aligned text";
146    rsgMeasureText(text, &left, &right, &top, &bottom);
147    rsgDrawText(text, width - right, height + bottom);
148
149}
150
151static void bindProgramVertexOrtho() {
152    // Default vertex sahder
153    rsgBindProgramVertex(gProgVertex);
154    // Setup the projectioni matrix
155    rs_matrix4x4 proj;
156    rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
157    rsgProgramVertexLoadProjectionMatrix(&proj);
158}
159
160static void displayShaderSamples() {
161    bindProgramVertexOrtho();
162    rs_matrix4x4 matrix;
163    rsMatrixLoadIdentity(&matrix);
164    rsgProgramVertexLoadModelMatrix(&matrix);
165
166    // Fragment shader with texture
167    rsgBindProgramStore(gProgStoreBlendNone);
168    rsgBindProgramFragment(gProgFragmentTexture);
169    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
170    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
171
172    float startX = 0, startY = 0;
173    float width = 256, height = 256;
174    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
175                         startX, startY + height, 0, 0, 1,
176                         startX + width, startY + height, 0, 1, 1,
177                         startX + width, startY, 0, 1, 0);
178
179    startX = 200; startY = 0;
180    width = 128; height = 128;
181    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
182                         startX, startY + height, 0, 0, 1,
183                         startX + width, startY + height, 0, 1, 1,
184                         startX + width, startY, 0, 1, 0);
185
186    rsgBindProgramStore(gProgStoreBlendAlpha);
187    rsgBindTexture(gProgFragmentTexture, 0, gTexTransparent);
188    startX = 0; startY = 200;
189    width = 128; height = 128;
190    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
191                         startX, startY + height, 0, 0, 1,
192                         startX + width, startY + height, 0, 1, 1,
193                         startX + width, startY, 0, 1, 0);
194
195    // Fragment program with simple color
196    rsgBindProgramFragment(gProgFragmentColor);
197    rsgProgramFragmentConstantColor(gProgFragmentColor, 0.9, 0.3, 0.3, 1);
198    rsgDrawRect(200, 300, 350, 450, 0);
199    rsgProgramFragmentConstantColor(gProgFragmentColor, 0.3, 0.9, 0.3, 1);
200    rsgDrawRect(50, 400, 400, 600, 0);
201
202    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
203    rsgBindFont(gFontMono);
204    rsgDrawText("Texture shader", 10, 50);
205    rsgDrawText("Alpha-blended texture shader", 10, 280);
206    rsgDrawText("Flat color shader", 100, 450);
207}
208
209static void displayBlendingSamples() {
210    int i;
211
212    bindProgramVertexOrtho();
213    rs_matrix4x4 matrix;
214    rsMatrixLoadIdentity(&matrix);
215    rsgProgramVertexLoadModelMatrix(&matrix);
216
217    rsgBindProgramFragment(gProgFragmentColor);
218
219    rsgBindProgramStore(gProgStoreBlendNone);
220    for (i = 0; i < 3; i ++) {
221        float iPlusOne = (float)(i + 1);
222        rsgProgramFragmentConstantColor(gProgFragmentColor,
223                                        0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1);
224        float yPos = 150 * (float)i;
225        rsgDrawRect(0, yPos, 200, yPos + 200, 0);
226    }
227
228    rsgBindProgramStore(gProgStoreBlendAlpha);
229    for (i = 0; i < 3; i ++) {
230        float iPlusOne = (float)(i + 1);
231        rsgProgramFragmentConstantColor(gProgFragmentColor,
232                                        0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5);
233        float yPos = 150 * (float)i;
234        rsgDrawRect(150, yPos, 350, yPos + 200, 0);
235    }
236
237    rsgBindProgramStore(gProgStoreBlendAdd);
238    for (i = 0; i < 3; i ++) {
239        float iPlusOne = (float)(i + 1);
240        rsgProgramFragmentConstantColor(gProgFragmentColor,
241                                        0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5);
242        float yPos = 150 * (float)i;
243        rsgDrawRect(300, yPos, 500, yPos + 200, 0);
244    }
245
246
247    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
248    rsgBindFont(gFontMono);
249    rsgDrawText("No Blending", 10, 50);
250    rsgDrawText("Alpha Blending", 160, 150);
251    rsgDrawText("Additive Blending", 320, 250);
252
253}
254
255static void displayMeshSamples() {
256
257    bindProgramVertexOrtho();
258    rs_matrix4x4 matrix;
259    rsMatrixLoadTranslate(&matrix, 128, 128, 0);
260    rsgProgramVertexLoadModelMatrix(&matrix);
261
262    // Fragment shader with texture
263    rsgBindProgramStore(gProgStoreBlendNone);
264    rsgBindProgramFragment(gProgFragmentTexture);
265    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
266    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
267
268    rsgDrawMesh(gMbyNMesh);
269
270    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
271    rsgBindFont(gFontMono);
272    rsgDrawText("User gen 10 by 10 grid mesh", 10, 250);
273}
274
275static void displayTextureSamplers() {
276
277    bindProgramVertexOrtho();
278    rs_matrix4x4 matrix;
279    rsMatrixLoadIdentity(&matrix);
280    rsgProgramVertexLoadModelMatrix(&matrix);
281
282    // Fragment shader with texture
283    rsgBindProgramStore(gProgStoreBlendNone);
284    rsgBindProgramFragment(gProgFragmentTexture);
285    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
286
287    // Linear clamp
288    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
289    float startX = 0, startY = 0;
290    float width = 300, height = 300;
291    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
292                         startX, startY + height, 0, 0, 1.1,
293                         startX + width, startY + height, 0, 1.1, 1.1,
294                         startX + width, startY, 0, 1.1, 0);
295
296    // Linear Wrap
297    rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap);
298    startX = 0; startY = 300;
299    width = 300; height = 300;
300    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
301                         startX, startY + height, 0, 0, 1.1,
302                         startX + width, startY + height, 0, 1.1, 1.1,
303                         startX + width, startY, 0, 1.1, 0);
304
305    // Nearest
306    rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp);
307    startX = 300; startY = 0;
308    width = 300; height = 300;
309    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
310                         startX, startY + height, 0, 0, 1.1,
311                         startX + width, startY + height, 0, 1.1, 1.1,
312                         startX + width, startY, 0, 1.1, 0);
313
314    rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
315    startX = 300; startY = 300;
316    width = 300; height = 300;
317    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
318                         startX, startY + height, 0, 0, 1.5,
319                         startX + width, startY + height, 0, 1.5, 1.5,
320                         startX + width, startY, 0, 1.5, 0);
321
322    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
323    rsgBindFont(gFontMono);
324    rsgDrawText("Filtering: linear clamp", 10, 290);
325    rsgDrawText("Filtering: linear wrap", 10, 590);
326    rsgDrawText("Filtering: nearest clamp", 310, 290);
327    rsgDrawText("Filtering: miplinear wrap", 310, 590);
328}
329
330static float gTorusRotation = 0;
331
332static void displayCullingSamples() {
333    rsgBindProgramVertex(gProgVertex);
334    // Setup the projectioni matrix with 60 degree field of view
335    rs_matrix4x4 proj;
336    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
337    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
338    rsgProgramVertexLoadProjectionMatrix(&proj);
339
340    // Fragment shader with texture
341    rsgBindProgramStore(gProgStoreBlendNoneDepth);
342    rsgBindProgramFragment(gProgFragmentTexture);
343    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
344    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
345
346    // Aplly a rotation to our mesh
347    gTorusRotation += 50.0f * gDt;
348    if (gTorusRotation > 360.0f) {
349        gTorusRotation -= 360.0f;
350    }
351
352    rs_matrix4x4 matrix;
353    // Position our model on the screen
354    rsMatrixLoadTranslate(&matrix, -2.0f, 0.0f, -10.0f);
355    rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
356    rsgProgramVertexLoadModelMatrix(&matrix);
357    // Use front face culling
358    rsgBindProgramRaster(gCullFront);
359    rsgDrawMesh(gTorusMesh);
360
361    rsMatrixLoadTranslate(&matrix, 2.0f, 0.0f, -10.0f);
362    rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
363    rsgProgramVertexLoadModelMatrix(&matrix);
364    // Use back face culling
365    rsgBindProgramRaster(gCullBack);
366    rsgDrawMesh(gTorusMesh);
367
368    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
369    rsgBindFont(gFontMono);
370    rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10);
371}
372
373static float gLight0Rotation = 0;
374static float gLight1Rotation = 0;
375
376static void setupCustomShaderLights() {
377    float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
378    float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
379    float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f};
380    float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f};
381    float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
382    float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
383
384    gLight0Rotation += 50.0f * gDt;
385    if (gLight0Rotation > 360.0f) {
386        gLight0Rotation -= 360.0f;
387    }
388    gLight1Rotation -= 50.0f * gDt;
389    if (gLight1Rotation > 360.0f) {
390        gLight1Rotation -= 360.0f;
391    }
392
393    rs_matrix4x4 l0Mat;
394    rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f);
395    light0Pos = rsMatrixMultiply(&l0Mat, light0Pos);
396    rs_matrix4x4 l1Mat;
397    rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f);
398    light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
399
400    // Set light 0 properties
401    gVSConstants->light0_Posision = light0Pos;
402    gVSConstants->light0_Diffuse = 1.0f;
403    gVSConstants->light0_Specular = 0.5f;
404    gVSConstants->light0_CosinePower = 10.0f;
405    // Set light 1 properties
406    gVSConstants->light1_Posision = light1Pos;
407    gVSConstants->light1_Diffuse = 1.0f;
408    gVSConstants->light1_Specular = 0.7f;
409    gVSConstants->light1_CosinePower = 25.0f;
410    rsgAllocationSyncAll(rsGetAllocation(gVSConstants));
411
412    gVSConstants2->light_Posision[0] = light0Pos;
413    gVSConstants2->light_Diffuse[0] = 1.0f;
414    gVSConstants2->light_Specular[0] = 0.5f;
415    gVSConstants2->light_CosinePower[0] = 10.0f;
416    gVSConstants2->light_Posision[1] = light1Pos;
417    gVSConstants2->light_Diffuse[1] = 1.0f;
418    gVSConstants2->light_Specular[1] = 0.7f;
419    gVSConstants2->light_CosinePower[1] = 25.0f;
420    rsgAllocationSyncAll(rsGetAllocation(gVSConstants2));
421
422    // Update fragmetn shader constants
423    // Set light 0 colors
424    gFSConstants->light0_DiffuseColor = light0DiffCol;
425    gFSConstants->light0_SpecularColor = light0SpecCol;
426    // Set light 1 colors
427    gFSConstants->light1_DiffuseColor = light1DiffCol;
428    gFSConstants->light1_SpecularColor = light1SpecCol;
429    rsgAllocationSyncAll(rsGetAllocation(gFSConstants));
430
431    gFSConstants2->light_DiffuseColor[0] = light0DiffCol;
432    gFSConstants2->light_SpecularColor[0] = light0SpecCol;
433    // Set light 1 colors
434    gFSConstants2->light_DiffuseColor[1] = light1DiffCol;
435    gFSConstants2->light_SpecularColor[1] = light1SpecCol;
436    rsgAllocationSyncAll(rsGetAllocation(gFSConstants2));
437}
438
439static void displayCustomShaderSamples() {
440
441    // Update vertex shader constants
442    // Load model matrix
443    // Aplly a rotation to our mesh
444    gTorusRotation += 50.0f * gDt;
445    if (gTorusRotation > 360.0f) {
446        gTorusRotation -= 360.0f;
447    }
448
449    // Position our model on the screen
450    rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f);
451    rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
452    rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
453    // Setup the projectioni matrix
454    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
455    rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
456    setupCustomShaderLights();
457
458    rsgBindProgramVertex(gProgVertexCustom);
459
460    // Fragment shader with texture
461    rsgBindProgramStore(gProgStoreBlendNoneDepth);
462    rsgBindProgramFragment(gProgFragmentCustom);
463    rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
464    rsgBindTexture(gProgFragmentCustom, 0, gTexTorus);
465
466    // Use back face culling
467    rsgBindProgramRaster(gCullBack);
468    rsgDrawMesh(gTorusMesh);
469
470    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
471    rsgBindFont(gFontMono);
472    rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10);
473}
474
475static void displayCustomShaderSamples2() {
476
477    // Update vertex shader constants
478    // Load model matrix
479    // Aplly a rotation to our mesh
480    gTorusRotation += 50.0f * gDt;
481    if (gTorusRotation > 360.0f) {
482        gTorusRotation -= 360.0f;
483    }
484
485    // Position our model on the screen
486    rsMatrixLoadTranslate(&gVSConstants2->model[1], 0.0f, 0.0f, -10.0f);
487    rsMatrixLoadIdentity(&gVSConstants2->model[0]);
488    rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 1.0f, 0.0f, 0.0f);
489    rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 0.0f, 0.0f, 1.0f);
490    // Setup the projectioni matrix
491    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
492    rsMatrixLoadPerspective(&gVSConstants2->proj, 30.0f, aspect, 0.1f, 100.0f);
493    setupCustomShaderLights();
494
495    rsgBindProgramVertex(gProgVertexCustom2);
496
497    // Fragment shader with texture
498    rsgBindProgramStore(gProgStoreBlendNoneDepth);
499    rsgBindProgramFragment(gProgFragmentCustom2);
500    rsgBindSampler(gProgFragmentCustom2, 0, gLinearClamp);
501    rsgBindTexture(gProgFragmentCustom2, 0, gTexTorus);
502
503    // Use back face culling
504    rsgBindProgramRaster(gCullBack);
505    rsgDrawMesh(gTorusMesh);
506
507    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
508    rsgBindFont(gFontMono);
509    rsgDrawText("Custom shader sample with array uniforms", 10, rsgGetHeight() - 10);
510}
511
512static void displayCubemapShaderSample() {
513    // Update vertex shader constants
514    // Load model matrix
515    // Aplly a rotation to our mesh
516    gTorusRotation += 50.0f * gDt;
517    if (gTorusRotation > 360.0f) {
518        gTorusRotation -= 360.0f;
519    }
520
521    // Position our model on the screen
522    // Position our model on the screen
523    rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f);
524    rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
525    rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
526    // Setup the projectioni matrix
527    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
528    rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
529    rsgAllocationSyncAll(rsGetAllocation(gFSConstants));
530
531    rsgBindProgramVertex(gProgVertexCube);
532
533    // Fragment shader with texture
534    rsgBindProgramStore(gProgStoreBlendNoneDepth);
535    rsgBindProgramFragment(gProgFragmentCube);
536    rsgBindSampler(gProgFragmentCube, 0, gLinearClamp);
537    rsgBindTexture(gProgFragmentCube, 0, gTexCube);
538
539    // Use back face culling
540    rsgBindProgramRaster(gCullBack);
541    rsgDrawMesh(gTorusMesh);
542
543    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
544    rsgBindFont(gFontMono);
545    rsgDrawText("Cubemap shader sample", 10, rsgGetHeight() - 10);
546}
547
548static void displayMultitextureSample() {
549    bindProgramVertexOrtho();
550    rs_matrix4x4 matrix;
551    rsMatrixLoadIdentity(&matrix);
552    rsgProgramVertexLoadModelMatrix(&matrix);
553
554    // Fragment shader with texture
555    rsgBindProgramStore(gProgStoreBlendNone);
556    rsgBindProgramFragment(gProgFragmentMultitex);
557    rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
558    rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
559    rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
560    rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
561    rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
562    rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
563
564    float startX = 0, startY = 0;
565    float width = 256, height = 256;
566    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
567                         startX, startY + height, 0, 0, 1,
568                         startX + width, startY + height, 0, 1, 1,
569                         startX + width, startY, 0, 1, 0);
570
571    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
572    rsgBindFont(gFontMono);
573    rsgDrawText("Custom shader with multitexturing", 10, 280);
574}
575
576static float gAnisoTime = 0.0f;
577static uint anisoMode = 0;
578static void displayAnisoSample() {
579
580    gAnisoTime += gDt;
581
582    rsgBindProgramVertex(gProgVertex);
583    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
584    rs_matrix4x4 proj;
585    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
586    rsgProgramVertexLoadProjectionMatrix(&proj);
587
588    rs_matrix4x4 matrix;
589    // Fragment shader with texture
590    rsgBindProgramStore(gProgStoreBlendNone);
591    rsgBindProgramFragment(gProgFragmentTexture);
592    rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f);
593    rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f);
594    rsgProgramVertexLoadModelMatrix(&matrix);
595
596    rsgBindProgramRaster(gCullNone);
597
598    rsgBindTexture(gProgFragmentTexture, 0, gTexChecker);
599
600    if (gAnisoTime >= 5.0f) {
601        gAnisoTime = 0.0f;
602        anisoMode ++;
603        anisoMode = anisoMode % 3;
604    }
605
606    if (anisoMode == 0) {
607        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8);
608    } else if (anisoMode == 1) {
609        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15);
610    } else {
611        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
612    }
613
614    float startX = -15;
615    float startY = -15;
616    float width = 30;
617    float height = 30;
618    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
619                         startX, startY + height, 0, 0, 10,
620                         startX + width, startY + height, 0, 10, 10,
621                         startX + width, startY, 0, 10, 0);
622
623    rsgBindProgramRaster(gCullBack);
624
625    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
626    rsgBindFont(gFontMono);
627    if (anisoMode == 0) {
628        rsgDrawText("Anisotropic filtering 8", 10, 40);
629    } else if (anisoMode == 1) {
630        rsgDrawText("Anisotropic filtering 15", 10, 40);
631    } else {
632        rsgDrawText("Miplinear filtering", 10, 40);
633    }
634}
635
636int root(void) {
637
638    gDt = rsGetDt();
639
640    rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
641    rsgClearDepth(1.0f);
642
643    switch (gDisplayMode) {
644    case 0:
645        displayFontSamples();
646        break;
647    case 1:
648        displayShaderSamples();
649        break;
650    case 2:
651        displayBlendingSamples();
652        break;
653    case 3:
654        displayMeshSamples();
655        break;
656    case 4:
657        displayTextureSamplers();
658        break;
659    case 5:
660        displayCullingSamples();
661        break;
662    case 6:
663        displayCustomShaderSamples();
664        break;
665    case 7:
666        displayMultitextureSample();
667        break;
668    case 8:
669        displayAnisoSample();
670        break;
671    case 9:
672        displayCustomShaderSamples2();
673        break;
674    case 10:
675        displayCubemapShaderSample();
676        break;
677    }
678
679    return 10;
680}
681