Skip to content

Instantly share code, notes, and snippets.

@RSDuck
Last active July 10, 2016 12:37
Show Gist options
  • Save RSDuck/66632a88b238fb917b7918b8a0fead94 to your computer and use it in GitHub Desktop.
Save RSDuck/66632a88b238fb917b7918b8a0fead94 to your computer and use it in GitHub Desktop.
Rendering
#include <stdio.h>
#include <string.h>
#include <citro3d.h>
#include "render.h"
#include "world.h"
#include "player.h"
#include "world_shbin.h"
#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 position[3];
float uv[2];
float color[3];
} world_vertex;
static DVLB_s* world_dvlb;
static shaderProgram_s world_shader;
static int world_shader_uLocProjection;
static int world_shader_uLocModelView;
static C3D_AttrInfo world_shader_attr;
static C3D_BufInfo world_shader_buffs;
static C3D_RenderTarget* target;
static C3D_Mtx projection;
enum Sides { Front = 0, Back, Right, Left, Top, Bottom };
// Shameless copied from https://github.com/devkitPro/3ds-examples/blob/master/graphics/gpu/textured_cube/source/main.c
static const world_vertex cube_sides_lut[] = {
// First face (PZ)
// First triangle
{{-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f}},
{{+0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, +1.0f}},
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f}},
// Second triangle
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f}},
{{-0.5f, +0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, +1.0f}},
{{-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f}},
// Second face (MZ)
// First triangle
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
{{-0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
{{+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
// Second triangle
{{+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{+0.5f, -0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
// Third face (PX)
// First triangle
{{+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f}},
{{+0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {+1.0f, 0.0f, 0.0f}},
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f}},
// Second triangle
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f}},
{{+0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {+1.0f, 0.0f, 0.0f}},
{{+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f}},
// Fourth face (MX)
// First triangle
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},
{{-0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},
{{-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
// Second triangle
{{-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
{{-0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},
// Fifth face (PY)
// First triangle
{{-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f}},
{{-0.5f, +0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, +1.0f, 0.0f}},
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f}},
// Second triangle
{{+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f}},
{{+0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, +1.0f, 0.0f}},
{{-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f}},
// Sixth face (MY)
// First triangle
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}},
{{+0.5f, -0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}},
{{+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
// Second triangle
{{+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
{{-0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}},
};
typedef struct {
u8 x, y, z, side;
Block block;
} Side;
inline Block failsafeBlockFetch(Cluster* c, int x, int y, int z) {
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_WIDTH || y >= CHUNK_CLUSTER_HEIGHT || z >= CHUNK_DEPTH) ? Block_Air : c->blocks[x][y][z];
}
static void TakeCareOfChunk(Chunk* chunk) {
for (int i = 0; i < CHUNK_HEIGHT / CHUNK_CLUSTER_HEIGHT; i++) {
Cluster* cluster = &chunk->data[i];
if (cluster->dirty & Cluster_DirtyVBO) {
chunk->vertexCount -= cluster->vertexCount;
static Side sides[6 * (CHUNK_WIDTH * CHUNK_CLUSTER_HEIGHT * CHUNK_DEPTH / 2)];
int sideCurrent = 0;
for (int x = 0; x < CHUNK_WIDTH; x++)
for (int z = 0; z < CHUNK_DEPTH; z++)
for (int y = 0; y < CHUNK_CLUSTER_HEIGHT; y++) {
if (cluster->blocks[x][y][z] != Block_Air) {
if (failsafeBlockFetch(cluster, x, y - 1, z) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Bottom, cluster->blocks[x][y][z]};
if (failsafeBlockFetch(cluster, x, y + 1, z) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Top, cluster->blocks[x][y][z]};
if (failsafeBlockFetch(cluster, x - 1, y, z) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Left, cluster->blocks[x][y][z]};
if (failsafeBlockFetch(cluster, x + 1, y, z) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Right, cluster->blocks[x][y][z]};
if (failsafeBlockFetch(cluster, x, y, z - 1) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Back, cluster->blocks[x][y][z]};
if (failsafeBlockFetch(cluster, x, y, z + 1) == Block_Air)
sides[sideCurrent++] = (Side){x, y, z, Front, cluster->blocks[x][y][z]};
}
}
/*{
FILE* f = fopen("sides.txt", "w");
int side = 0;
while (side < sideCurrent) {
fprintf(f, "%d\t|%d\t|%d, %d, %d\n", sides[side].block, sides[side].side, sides[side].x, sides[side].y, sides[side].z);
side++;
}
fclose(f);
}*/
if (cluster->vbo == NULL || cluster->vboSize == 0) {
cluster->vboSize = sizeof(world_vertex) * 6 * sideCurrent;
cluster->vbo = linearAlloc(cluster->vboSize);
} else if (cluster->vboSize < sizeof(world_vertex) * 6 * sideCurrent) {
linearFree(cluster->vbo);
cluster->vboSize = sizeof(world_vertex) * 6 * sideCurrent;
cluster->vbo = linearAlloc(cluster->vboSize);
}
int vertexCount = 0;
world_vertex* ptr = (world_vertex*)cluster->vbo;
for (int j = 0; j < sideCurrent; j++) {
memcpy(ptr, &cube_sides_lut[sides[j].side * 6], sizeof(world_vertex) * 6);
const world_vertex* sideVtxs = &cube_sides_lut[sides[j].side * 6];
for (int k = 0; k < 6; k++) {
// ptr[k] = sideVtxs[k];
ptr[k].position[0] += (float)sides[j].x;
ptr[k].position[1] += (float)sides[j].y;
ptr[k].position[2] += (float)sides[j].z;
}
ptr += 6;
vertexCount += 6;
}
/*{
FILE* f = fopen("verts.txt", "w");
world_vertex* dPtr = (world_vertex*)cluster->vbo;
while (dPtr != ptr) {
fprintf(f, "%f, %f, %f\t| %f, %f\t| %f, %f, %f\n", dPtr->position[0], dPtr->position[1], dPtr->position[2], dPtr->uv[0],
dPtr->uv[1], dPtr->color[0], dPtr->color[1], dPtr->color[2]);
dPtr++;
}
fclose(f);
}*/
cluster->vertexCount = vertexCount;
chunk->vertexCount += vertexCount;
printf("%d, %d\n", sideCurrent, vertexCount);
Cluster_UnmarkDirty(cluster, Cluster_DirtyVBO);
}
}
}
float* testCubeVBO;
void Render_Init() {
gfxInitDefault();
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
// Initialize the render target
target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, 0x000000FF, 0);
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
world_dvlb = DVLB_ParseFile((u32*)world_shbin, world_shbin_size);
shaderProgramInit(&world_shader);
shaderProgramSetVsh(&world_shader, &world_dvlb->DVLE[0]);
C3D_BindProgram(&world_shader);
world_shader_uLocProjection = shaderInstanceGetUniformLocation(world_shader.vertexShader, "projection");
world_shader_uLocModelView = shaderInstanceGetUniformLocation(world_shader.vertexShader, "modelView");
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo);
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2);
AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 3); // v1=color
// Compute the projection matrix
Mtx_PerspTilt(&projection, 80.0f * M_PI / 180.0f, 400.0f / 240.0f, 0.01f, 1000.0f);
// Create the VBO (vertex buffer object)
testCubeVBO = linearAlloc(sizeof(cube_sides_lut));
memcpy(testCubeVBO, cube_sides_lut, sizeof(cube_sides_lut));
printf("TestCubeVBO created\n");
// Configure buffers
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, testCubeVBO, sizeof(world_vertex), 3, 0x210);
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);
}
void Render_Exit() {
linearFree(testCubeVBO);
shaderProgramFree(&world_shader);
DVLB_Free(world_dvlb);
C3D_Fini();
gfxExit();
}
extern int a;
void Render(Player* player) {
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_FrameDrawOn(target);
C3D_Mtx modelview;
Mtx_Identity(&modelview);
Mtx_Translate(&modelview, -player->x, -player->y, -player->z);
Mtx_RotateY(&modelview, player->yaw, true);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, world_shader_uLocProjection, &projection);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, world_shader_uLocModelView, &modelview);
printf("Frame start\n");
ChunkCache* cache = player->cache;
for (int x = 0; x < CACHE_SIZE; x++) {
for (int z = 0; z < CACHE_SIZE; z++) {
Chunk* c = cache->cache[x][z];
if (c->dirty & Cluster_DirtyVBO) {
TakeCareOfChunk(c);
c->dirty &= ~Cluster_DirtyVBO;
// printf("Unmarken chunk %d, %d dirty\n", c->x, c->z);
}
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
// for (int i = 0; i < CHUNK_HEIGHT / CHUNK_CLUSTER_HEIGHT; i++)
if (c->data[0].vbo) BufInfo_Add(bufInfo, c->data[0].vbo, sizeof(world_vertex), 3, 0x210);
C3D_DrawArrays(GPU_TRIANGLES, 0, c->vertexCount - (a * 3));
printf("Drawing %d triangles\n", c->vertexCount);
break;
}
break;
}
// C3D_DrawArrays(GPU_TRIANGLES, 0, 36);
C3D_FrameEnd(0);
// C3D_VideoSync();
}
; World Shader for rendering blocks
; Uniforms
.fvec projection[4]
.fvec modelView[4]
; Constants
.constf myconst(0.0, 1.0, -1.0, 0.1)
.constf myconst2(0.3, 0.0, 0.0, 0.0)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
; Outputs
.out outpos position
.out outclr color
; Inputs (defined as aliases for convenience)
.alias inpos v0
.alias inuv v1
.alias inclr v2
.proc main
; Force the w component of inpos to be 1.0
mov r0.xyz, inpos
mov r0.w, ones
dp4 r1.x, modelView[0], r0
dp4 r1.y, modelView[1], r0
dp4 r1.z, modelView[2], r0
dp4 r1.w, modelView[3], r0
dp4 outpos.x, projection[0], r1
dp4 outpos.y, projection[1], r1
dp4 outpos.z, projection[2], r1
dp4 outpos.w, projection[3], r1
; outclr = inclr
mov outclr, inclr
mov outclr.w, ones
; We're finished
end
.end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment