Created
June 6, 2017 17:13
-
-
Save Subv/a22bf6f9796e7e1c967c14c2c365f3b4 to your computer and use it in GitHub Desktop.
Nintendo 3DS PICA GPU Blend factors test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <3ds.h> | |
#include <citro3d.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include "vshader_shbin.h" | |
#define CLEAR_COLOR 0x68B0D8FF | |
#define DISPLAY_TRANSFER_FLAGS \ | |
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \ | |
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ | |
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) | |
typedef struct { float x, y, z; } vertex; | |
static const vertex vertex_list[] = | |
{ | |
{ 200.0f, 200.0f, 0.5f }, | |
{ 100.0f, 40.0f, 0.5f }, | |
{ 300.0f, 40.0f, 0.5f }, | |
}; | |
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0])) | |
static DVLB_s* vshader_dvlb; | |
static shaderProgram_s program; | |
static int uLoc_projection; | |
static C3D_Mtx projection; | |
static void* vbo_data; | |
static void sceneInit(void) | |
{ | |
// Load the vertex shader, create a shader program and bind it | |
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size); | |
shaderProgramInit(&program); | |
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]); | |
C3D_BindProgram(&program); | |
// Get the location of the uniforms | |
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); | |
// Configure attributes for use with the vertex shader | |
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); | |
AttrInfo_Init(attrInfo); | |
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position | |
AttrInfo_AddFixed(attrInfo, 1); // v1=color | |
// Set the fixed attribute (color) to solid white | |
C3D_FixedAttribSet(1, 1.0, 1.0, 1.0, 1.0); | |
// Compute the projection matrix | |
Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); | |
// Create the VBO (vertex buffer object) | |
vbo_data = linearAlloc(sizeof(vertex_list)); | |
memcpy(vbo_data, vertex_list, sizeof(vertex_list)); | |
// Configure buffers | |
C3D_BufInfo* bufInfo = C3D_GetBufInfo(); | |
BufInfo_Init(bufInfo); | |
BufInfo_Add(bufInfo, vbo_data, sizeof(vertex), 1, 0x0); | |
// Configure the first fragment shading substage to just pass through the vertex color | |
// See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight | |
C3D_TexEnv* env = C3D_GetTexEnv(0); | |
C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0); | |
C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); | |
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); | |
} | |
static void sceneRender(void) | |
{ | |
// Update the uniforms | |
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); | |
// Draw the VBO | |
C3D_DrawArrays(GPU_TRIANGLES, 0, vertex_list_count); | |
} | |
static void sceneExit(void) | |
{ | |
// Free the VBO | |
linearFree(vbo_data); | |
// Free the shader program | |
shaderProgramFree(&program); | |
DVLB_Free(vshader_dvlb); | |
} | |
int main() | |
{ | |
// Initialize graphics | |
gfxInitDefault(); | |
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); | |
consoleInit(GFX_BOTTOM, NULL); | |
// Initialize the render target | |
C3D_RenderTarget* target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); | |
C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0); | |
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); | |
// Initialize the scene | |
sceneInit(); | |
enum { | |
ZERO_SRCC_ONE_DSTC = 0, | |
ONE_SRCC_ZERO_DSTC = 1, | |
ZERO_SRCA_ONE_DSTA = 2, | |
ONE_SRCA_ZERO_DSTA = 3, | |
ONE_SRCC_ONE_DSTC = 4, | |
} blend_test = ZERO_SRCC_ONE_DSTC; | |
u32 operation = GPU_BLEND_MAX; | |
// Main loop | |
while (aptMainLoop()) | |
{ | |
hidScanInput(); | |
// Respond to user input | |
u32 kDown = hidKeysDown(); | |
if (kDown & KEY_START) | |
break; // break in order to return to hbmenu | |
if (kDown & KEY_A) | |
blend_test++; | |
else if (kDown & KEY_B) | |
blend_test--; | |
else if (kDown & KEY_X) | |
operation = operation == GPU_BLEND_MAX ? GPU_BLEND_MIN : GPU_BLEND_MAX; | |
consoleClear(); | |
printf("Op %s Test mode %d\n", operation == GPU_BLEND_MAX ? "MAX" : "MIN", blend_test); | |
switch (blend_test) { | |
case ZERO_SRCC_ONE_DSTC: | |
// Zero src color, One dest color, should not show the triangle with max | |
C3D_AlphaBlend(operation, GPU_BLEND_ADD, GPU_ZERO, GPU_ONE, GPU_ONE, GPU_ZERO); | |
break; | |
case ONE_SRCC_ZERO_DSTC: | |
// One src color, Zero dest color, should show the triangle with max | |
C3D_AlphaBlend(operation, GPU_BLEND_ADD, GPU_ONE, GPU_ZERO, GPU_ONE, GPU_ZERO); | |
break; | |
case ZERO_SRCA_ONE_DSTA: | |
// Zero src alpha, One dest alpha, should show the triangle with max | |
C3D_AlphaBlend(operation, GPU_BLEND_ADD, GPU_ONE, GPU_ZERO, GPU_ZERO, GPU_ONE); | |
break; | |
case ONE_SRCA_ZERO_DSTA: | |
// One src alpha, Zero dest alpha, should show the triangle with max | |
C3D_AlphaBlend(operation, GPU_BLEND_ADD, GPU_ONE, GPU_ZERO, GPU_ONE, GPU_ZERO); | |
break; | |
case ONE_SRCC_ONE_DSTC: | |
// One src color, One dest color, should show the triangle in white with max | |
C3D_AlphaBlend(operation, GPU_BLEND_ADD, GPU_ONE, GPU_ZERO, GPU_ONE, GPU_ZERO); | |
break; | |
} | |
// Render the scene | |
C3D_FrameBegin(C3D_FRAME_SYNCDRAW); | |
C3D_FrameDrawOn(target); | |
sceneRender(); | |
C3D_FrameEnd(0); | |
} | |
// Deinitialize the scene | |
sceneExit(); | |
// Deinitialize graphics | |
C3D_Fini(); | |
gfxExit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment