void Sprite::render() { if (dirtyPixels) { dirtyPixels = false; GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel); C3D_SafeDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS); gspWaitForPPF(); } C3D_TexBind(0, &texture); C3D_BufInfo *bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); BufInfo_Add(bufInfo, vertices, sizeof(vertex), 2, 0x10); C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4); }
//--------------------------------------------------------------------------------- static void sceneInit(void) { //--------------------------------------------------------------------------------- int i; // 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 // Attribute format and element count are ignored in immediate mode C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v2=texcoord // Compute the projection matrix // Note: we're setting top to 240 here so origin is at top left. Mtx_OrthoTilt(&projection, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0); // Configure buffers C3D_BufInfo* bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); unsigned char* image; unsigned width, height; lodepng_decode32(&image, &width, &height, ballsprites_png, ballsprites_png_size); u8 *gpusrc = linearAlloc(width*height*4); // GX_DisplayTransfer needs input buffer in linear RAM u8* src=image; u8 *dst=gpusrc; // lodepng outputs big endian rgba so we need to convert for(int i = 0; i<width*height; i++) { int r = *src++; int g = *src++; int b = *src++; int a = *src++; *dst++ = a; *dst++ = b; *dst++ = g; *dst++ = r; } // ensure data is in physical ram GSPGPU_FlushDataCache(gpusrc, width*height*4); // Load the texture and bind it to the first texture unit C3D_TexInit(&spritesheet_tex, width, height, GPU_RGBA8); // Convert image to 3DS tiled texture format C3D_SafeDisplayTransfer ((u32*)gpusrc, GX_BUFFER_DIM(width,height), (u32*)spritesheet_tex.data, GX_BUFFER_DIM(width,height), TEXTURE_TRANSFER_FLAGS); gspWaitForPPF(); C3D_TexSetFilter(&spritesheet_tex, GPU_LINEAR, GPU_NEAREST); C3D_TexBind(0, &spritesheet_tex); free(image); linearFree(gpusrc); // Configure the first fragment shading substage to just pass through the texture 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_TEXTURE0, 0, 0); C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); srand(time(NULL)); for(i = 0; i < NUM_SPRITES; i++) { //random place and speed sprites[i].x = (rand() % (400 - 32 )) << 8; sprites[i].y = (rand() % (240 - 32 )) << 8 ; sprites[i].dx = (rand() & 0xFF) + 0x100; sprites[i].dy = (rand() & 0xFF) + 0x100; sprites[i].image = rand() & 3; if(rand() & 1) sprites[i].dx = -sprites[i].dx; if(rand() & 1) sprites[i].dy = -sprites[i].dy; } // Configure depth test to overwrite pixels with the same depth (needed to draw overlapping sprites) C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); }