Last active
July 10, 2016 12:37
-
-
Save RSDuck/66632a88b238fb917b7918b8a0fead94 to your computer and use it in GitHub Desktop.
Rendering
This file contains 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 <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(); | |
} |
This file contains 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
; 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