void TextEngine::renderText(float x, float y, float scaleX, float scaleY, bool baseline, const char* text)
{		
	ssize_t  units;
	uint32_t code;

	// Configure buffers
	C3D_BufInfo* bufInfo = C3D_GetBufInfo();
	BufInfo_Init(bufInfo);
	BufInfo_Add(bufInfo, textVtxArray, sizeof(textVertex_s), 2, 0x10);

	const uint8_t* p = (const uint8_t*)text;
	float firstX = x;
	u32 flags = GLYPH_POS_CALC_VTXCOORD | (baseline ? GLYPH_POS_AT_BASELINE : 0);
	int lastSheet = -1;
	do
	{
		if (!*p) break;
		units = decode_utf8(&code, p);
		if (units == -1)
			break;
		p += units;
		if (code == '\n')
		{
			x = firstX;
			y += scaleY*fontGetInfo()->lineFeed;
		}
		else if (code > 0)
		{
			int glyphIdx = fontGlyphIndexFromCodePoint(code);
			fontGlyphPos_s data;
			fontCalcGlyphPos(&data, glyphIdx, flags, scaleX, scaleY);

			// Bind the correct texture sheet
			if (data.sheetIndex != lastSheet)
			{
				lastSheet = data.sheetIndex;
				C3D_TexBind(0, &glyphSheets[lastSheet]);
			}

			int arrayIndex = textVtxArrayPos;
			if ((arrayIndex+4) >= TEXT_VTX_ARRAY_COUNT)
				break; // We can't render more characters

			// Add the vertices to the array
			addTextVertex(x+data.vtxcoord.left,  y+data.vtxcoord.bottom, data.texcoord.left,  data.texcoord.bottom);
			addTextVertex(x+data.vtxcoord.right, y+data.vtxcoord.bottom, data.texcoord.right, data.texcoord.bottom);
			addTextVertex(x+data.vtxcoord.left,  y+data.vtxcoord.top,    data.texcoord.left,  data.texcoord.top);
			addTextVertex(x+data.vtxcoord.right, y+data.vtxcoord.top,    data.texcoord.right, data.texcoord.top);

			// Draw the glyph
			C3D_DrawArrays(GPU_TRIANGLE_STRIP, arrayIndex, 4);

			x += data.xAdvance;

		}
	} while (code > 0);
}
Example #2
0
void BackgroundImpl::draw() const {
    if (options) {
        // Draw settings background
        C3D_TexBind(0, &empty_tex);
        C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP);

        C3D_ImmSendAttrib(0.0f, 0.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 1.0f);

        C3D_ImmSendAttrib(0.0f, 240.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);

        C3D_ImmSendAttrib(400.0f, 0.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 1.0f);

        C3D_ImmSendAttrib(400.0f, 240.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);

        C3D_ImmDrawEnd();
    } else {
        // Draw game background
        C3D_TexBind(0, &background_tex);
        C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP);

        C3D_ImmSendAttrib(0.0f, 0.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(1.0f, 1.0f, 1.0f, 1.0f);

        C3D_ImmSendAttrib(0.0f, 240.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0.0f, 240.0f / 256.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(1.0f, 1.0f, 1.0f, 1.0f);

        C3D_ImmSendAttrib(400.0f, 0.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(400.0f / 512.0f, 0.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(1.0f, 1.0f, 1.0f, 1.0f);

        C3D_ImmSendAttrib(400.0f, 240.0f, 0.5f, 0.0f);
        C3D_ImmSendAttrib(400.0f / 512.0f, 240.0f / 256.0f, 0.0f, 0.0f);
        C3D_ImmSendAttrib(1.0f, 1.0f, 1.0f, 1.0f);

        C3D_ImmDrawEnd();
    }
}
Example #3
0
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);
}
Example #4
0
void ctrActivateTexture(C3D_Tex* texture) {
	if (texture == activeTexture) {
		return;
	}
	if (activeTexture) {
		ctrFlushBatch();
	}

	activeTexture = texture;
	C3D_TexBind(0, activeTexture);

	C3D_TexEnv* env = C3D_GetTexEnv(0);
	C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
	if (texture->fmt < GPU_LA8) {
		C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0);
		C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
	} else {
		C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, 0, 0);
		C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0);
		C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
		C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
	}
	env = C3D_GetTexEnv(1);
	C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
	C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, 0, 0);
	C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
	env = C3D_GetTexEnv(2);
	C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
	C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, 0, 0);
	C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);

	C3D_Mtx textureMtx = {
		.m = {
			// Rows are in the order w z y x, because ctrulib
			0.0f, 0.0f, 0.0f, 1.0f / activeTexture->width,
			0.0f, 0.0f, 1.0f / activeTexture->height, 0.0f 
		}
	};
	C3D_FVUnifMtx2x4(GPU_GEOMETRY_SHADER, GSH_FVEC_textureMtx, &textureMtx);
}
Example #5
0
void TextImpl::draw() const {
    C3D_TexBind(0, &text_tex);

    C3D_ImmDrawBegin(GPU_TRIANGLES);

    // We have only one color per Text object
    // TODO color

    for (unsigned int i = 0; i < m_quads_len; ++i) {
        C3D_ImmSendAttrib(m_quads[i].verts[0].x, m_quads[i].verts[0].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[0].u, m_quads[i].verts[0].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);

        C3D_ImmSendAttrib(m_quads[i].verts[2].x, m_quads[i].verts[2].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[2].u, m_quads[i].verts[2].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);

        C3D_ImmSendAttrib(m_quads[i].verts[1].x, m_quads[i].verts[1].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[1].u, m_quads[i].verts[1].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);

        C3D_ImmSendAttrib(m_quads[i].verts[0].x, m_quads[i].verts[0].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[0].u, m_quads[i].verts[0].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);

        C3D_ImmSendAttrib(m_quads[i].verts[3].x, m_quads[i].verts[3].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[3].u, m_quads[i].verts[3].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);

        C3D_ImmSendAttrib(m_quads[i].verts[2].x, m_quads[i].verts[2].y, 0.5f, 0.0f);
        C3D_ImmSendAttrib(m_quads[i].verts[2].u, m_quads[i].verts[2].v, 0.0f, 0.0f);
        C3D_ImmSendAttrib(m_quads[0].verts[0].r, m_quads[0].verts[0].g, m_quads[0].verts[0].b, m_quads[0].verts[0].a);
    }

    C3D_ImmDrawEnd();
}
Example #6
0
//---------------------------------------------------------------------------------
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);
}
Example #7
0
void gfxDrawScreen() {
    int screenTexSize = 256;
    u32* transferBuffer = screenBuffer;
    GPU_TEXTURE_FILTER_PARAM filter = GPU_NEAREST;

    if(scaleMode != 0 && scaleFilter != 0) {
        filter = GPU_LINEAR;

        if(scaleFilter == 2) {
            screenTexSize = 512;
            transferBuffer = scale2xBuffer;

            gfxScale2xRGBA8888(screenBuffer, 256, scale2xBuffer, 512, 256, 224);
        }
    }

    if(!screenInit || screenTexture.width != screenTexSize || screenTexture.height != screenTexSize) {
        if(screenInit) {
            C3D_TexDelete(&screenTexture);
            screenInit = false;
        }

        screenInit = C3D_TexInit(&screenTexture, screenTexSize, screenTexSize, GPU_RGBA8);
    }

    C3D_TexSetFilter(&screenTexture, filter, filter);

    GSPGPU_FlushDataCache(transferBuffer, screenTexSize * screenTexSize * sizeof(u32));
    if(R_SUCCEEDED(GX_DisplayTransfer(transferBuffer, (u32) GX_BUFFER_DIM(screenTexSize, screenTexSize), (u32*) screenTexture.data, (u32) GX_BUFFER_DIM(screenTexSize, screenTexSize), GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)))) {
        gspWaitForPPF();
    }

    GSPGPU_InvalidateDataCache(screenTexture.data, screenTexture.size);

    if(!C3D_FrameBegin(0)) {
        return;
    }

    C3D_RenderTarget* target = gameScreen == 0 ? targetTop : targetBottom;

    C3D_FrameDrawOn(target);
    C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, shaderInstanceGetUniformLocation(program.vertexShader, "projection"), gameScreen == 0 ? &projectionTop : &projectionBottom);

    u16 viewportWidth = target->renderBuf.colorBuf.height;
    u16 viewportHeight = target->renderBuf.colorBuf.width;

    // Draw the screen.
    if(screenInit) {
        // Calculate the VBO dimensions.
        int screenWidth = 256;
        int screenHeight = 224;
        if(scaleMode == 1) {
            screenWidth *= 1.25f;
            screenHeight *= 1.25f;
        } else if(scaleMode == 2) {
            screenWidth *= 1.50f;
            screenHeight *= 1.50f;
        } else if(scaleMode == 3) {
            screenWidth *= viewportHeight / (float) screenHeight;
            screenHeight = viewportHeight;
        } else if(scaleMode == 4) {
            screenWidth = viewportWidth;
            screenHeight = viewportHeight;
        }

        // Calculate VBO points.
        const float x1 = ((int) viewportWidth - screenWidth) / 2.0f;
        const float y1 = ((int) viewportHeight - screenHeight) / 2.0f;
        const float x2 = x1 + screenWidth;
        const float y2 = y1 + screenHeight;

        static const float baseTX2 = 256.0f / 256.0f;
        static const float baseTY2 = 224.0f / 256.0f;
        static const float baseFilterMod = 0.25f / 256.0f;

        float tx2 = baseTX2;
        float ty2 = baseTY2;
        if(scaleMode != 0 && scaleFilter == 1) {
            tx2 -= baseFilterMod;
            ty2 -= baseFilterMod;
        }

        C3D_TexBind(0, &screenTexture);

        C3D_ImmDrawBegin(GPU_TRIANGLES);

        C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, ty2, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x1, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, ty2, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, ty2, 0.0f, 0.0f);

        C3D_ImmDrawEnd();
    }

    // Draw the border.
    if(borderInit && scaleMode != 4) {
        // Calculate VBO points.
        int scaledBorderWidth = borderWidth;
        int scaledBorderHeight = borderHeight;
        if(borderScaleMode == 1) {
            if(scaleMode == 1) {
                scaledBorderWidth *= 1.25f;
                scaledBorderHeight *= 1.25f;
            } else if(scaleMode == 2) {
                scaledBorderWidth *= 1.50f;
                scaledBorderHeight *= 1.50f;
            } else if(scaleMode == 3) {
                scaledBorderWidth *= viewportHeight / 224.0f;
                scaledBorderHeight *= viewportHeight / 224.0f;
            } else if(scaleMode == 4) {
                scaledBorderWidth *= viewportWidth / 256.0f;
                scaledBorderHeight *= viewportHeight / 224.0f;
            }
        }

        const float x1 = ((int) viewportWidth - scaledBorderWidth) / 2.0f;
        const float y1 = ((int) viewportHeight - scaledBorderHeight) / 2.0f;
        const float x2 = x1 + scaledBorderWidth;
        const float y2 = y1 + scaledBorderHeight;

        float tx2 = (float) borderWidth / (float) gpuBorderWidth;
        float ty2 = (float) borderHeight / (float) gpuBorderHeight;

        C3D_TexBind(0, &borderTexture);

        C3D_ImmDrawBegin(GPU_TRIANGLES);

        C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, ty2, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, 0, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x1, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(0, ty2, 0.0f, 0.0f);

        C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
        C3D_ImmSendAttrib(tx2, ty2, 0.0f, 0.0f);

        C3D_ImmDrawEnd();
    }

    C3D_FrameEnd(0);
}