Allow multiple materials per scene; misc. improvements

This commit is contained in:
Shylie 2024-04-24 14:41:50 -04:00
parent cd32e98c23
commit dceb378111
2 changed files with 88 additions and 49 deletions

View File

@ -18,7 +18,6 @@ struct vertex
float st[2]; float st[2];
float coords[3]; float coords[3];
float uv[2]; float uv[2];
float rand[4];
}; };
static DVLB_s* vshaderDVLB; static DVLB_s* vshaderDVLB;
@ -27,6 +26,7 @@ static s8 spheresUniformLocation;
static s8 sphereColorsUniformLocation; static s8 sphereColorsUniformLocation;
static s8 sphereLightsUniformLocation; static s8 sphereLightsUniformLocation;
static s8 randUniformLocation; static s8 randUniformLocation;
static s8 calcSphereLoopParamsUniformLocation;
static constexpr unsigned int VERTEX_COUNT_W = 150; static constexpr unsigned int VERTEX_COUNT_W = 150;
static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6; static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6;
@ -99,7 +99,6 @@ static float rand01()
static C3D_FVec randvec() static C3D_FVec randvec()
{ {
C3D_FVec out; C3D_FVec out;
out.w = rand01();
do do
{ {
@ -109,6 +108,9 @@ static C3D_FVec randvec()
} }
while (FVec3_Magnitude(out) > 1.0f); while (FVec3_Magnitude(out) > 1.0f);
out = FVec3_Normalize(out);
out.w = rand01();
return out; return out;
} }
@ -123,7 +125,7 @@ static void setupVertices()
const float s = static_cast<float>(x) / VERTEX_COUNT_W; const float s = static_cast<float>(x) / VERTEX_COUNT_W;
const float t = static_cast<float>(y) / VERTEX_COUNT_H; const float t = static_cast<float>(y) / VERTEX_COUNT_H;
// swapped due to 3DS screen orientation // s and t are swapped due to 3DS screen orientation
v.st[0] = t + rand01() / VERTEX_COUNT_W; v.st[0] = t + rand01() / VERTEX_COUNT_W;
v.st[1] = s + rand01() / VERTEX_COUNT_H; v.st[1] = s + rand01() / VERTEX_COUNT_H;
@ -141,20 +143,12 @@ static void setupVertices()
static void setupRandom() static void setupRandom()
{ {
constexpr int NUM_RAND = 20; constexpr int NUM_RAND = 15; // needs to be the same as rand array length in vshader.v.pica
C3D_FVec* randPtr = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, randUniformLocation, NUM_RAND); C3D_FVec* randPtr = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, randUniformLocation, NUM_RAND);
for (int i = 0; i < NUM_RAND; i++) for (int i = 0; i < NUM_RAND; i++)
{ {
randPtr[i] = randvec(); randPtr[i] = randvec();
} }
for (int i = 0; i < VERTEX_COUNT; i++)
{
vertex& v = static_cast<vertex*>(vboData)[i];
const C3D_FVec r = randvec();
memcpy(v.rand, r.c, sizeof(r.c));
}
} }
static void sceneInit() static void sceneInit()
@ -184,6 +178,7 @@ static void sceneInit()
sphereColorsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereColors"); sphereColorsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereColors");
sphereLightsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereLights"); sphereLightsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereLights");
randUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "rand"); randUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "rand");
calcSphereLoopParamsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "calcSphereLoopParams");
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo); AttrInfo_Init(attrInfo);
@ -194,14 +189,13 @@ static void sceneInit()
AttrInfo_AddLoader(attrInfo, 4, GPU_FLOAT, 2); AttrInfo_AddLoader(attrInfo, 4, GPU_FLOAT, 2);
AttrInfo_AddLoader(attrInfo, 5, GPU_FLOAT, 3); AttrInfo_AddLoader(attrInfo, 5, GPU_FLOAT, 3);
AttrInfo_AddLoader(attrInfo, 6, GPU_FLOAT, 2); AttrInfo_AddLoader(attrInfo, 6, GPU_FLOAT, 2);
AttrInfo_AddLoader(attrInfo, 7, GPU_FLOAT, 4);
iboData = linearAlloc(sizeof(vertexIndices)); iboData = linearAlloc(sizeof(vertexIndices));
memcpy(iboData, vertexIndices, sizeof(vertexIndices)); memcpy(iboData, vertexIndices, sizeof(vertexIndices));
C3D_BufInfo* bufInfo = C3D_GetBufInfo(); C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo); BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, vboData, sizeof(vertex), 4, 0x7654); BufInfo_Add(bufInfo, vboData, sizeof(vertex), 3, 0x654);
C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env); C3D_TexEnvInit(env);
@ -210,23 +204,25 @@ static void sceneInit()
C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE); C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
constexpr u16 NUM_SPHERES = 4; constexpr u16 NUM_SPHERES = 4;
C3D_IVUnifSet(GPU_VERTEX_SHADER, calcSphereLoopParamsUniformLocation, NUM_SPHERES - 1, 0, 1, 0);
C3D_FVec* spheres = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, spheresUniformLocation, NUM_SPHERES); C3D_FVec* spheres = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, spheresUniformLocation, NUM_SPHERES);
spheres[0] = FVec4_New(0.0f, -100.5f, -1.0f, 100.0f); spheres[0] = FVec4_New(0.0f, -100.5f, 0.0f, 100.0f);
spheres[1] = FVec4_New(0.6f, 0.0f, -1.0f, 0.5f); spheres[1] = FVec4_New(0.6f, 0.0f, 0.0f, 0.5f);
spheres[2] = FVec4_New(-0.6f, 0.0f, -1.0f, 0.5f); spheres[2] = FVec4_New(-0.6f, 0.0f, 0.0f, 0.5f);
spheres[3] = FVec4_New(0.0f, 10.0f, -1.0f, 9.0f); spheres[3] = FVec4_New(0.0f, 10.0f, 0.0f, 9.0f);
C3D_FVec* sphereColors = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereColorsUniformLocation, NUM_SPHERES); C3D_FVec* sphereColors = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereColorsUniformLocation, NUM_SPHERES);
sphereColors[0] = FVec3_New(0.9f, 0.3f, 0.3f); sphereColors[0] = FVec4_New(0.9f, 0.3f, 0.3f, 0);
sphereColors[1] = FVec3_New(0.3f, 0.9f, 0.3f); sphereColors[1] = FVec4_New(0.3f, 0.9f, 0.3f, 1);
sphereColors[2] = FVec3_New(0.3f, 0.3f, 0.9f); sphereColors[2] = FVec4_New(0.3f, 0.3f, 0.9f, 0);
sphereColors[3] = FVec3_New(1.0f, 1.0f, 1.0f); sphereColors[3] = FVec4_New(1.0f, 1.0f, 1.0f, -1);
C3D_FVec* sphereLights = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereLightsUniformLocation, NUM_SPHERES); C3D_FVec* sphereLights = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereLightsUniformLocation, NUM_SPHERES);
sphereLights[0] = FVec3_New(0.0f, 0.0f, 0.0f); sphereLights[0] = FVec4_New(0.0f, 0.0f, 0.0f, 0);
sphereLights[1] = FVec3_New(0.0f, 0.0f, 0.0f); sphereLights[1] = FVec4_New(0.0f, 0.0f, 0.0f, 0.2f);
sphereLights[2] = FVec3_New(0.0f, 0.0f, 0.0f); sphereLights[2] = FVec4_New(0.0f, 0.0f, 0.0f, 0);
sphereLights[3] = FVec3_New(1.0f, 1.0f, 1.0f); sphereLights[3] = FVec4_New(0.5f, 0.5f, 0.5f, 0);
} }
static void sceneRender() static void sceneRender()
@ -280,8 +276,8 @@ int main(int argc, char* argv[])
sceneInit(); sceneInit();
C3D_FVec lookFrom = FVec3_New(0, 0.6125f, 0); C3D_FVec lookFrom = FVec3_New(0, 0.0f, 1.0f);
C3D_FVec lookAt = FVec3_New(0, 0, -1.0f); C3D_FVec lookAt = FVec3_New(0, 0, 0.0f);
C3D_FVec vup = FVec3_New(0, 1.0f, 0); C3D_FVec vup = FVec3_New(0, 1.0f, 0);
bool dirty = true; bool dirty = true;
@ -352,7 +348,7 @@ int main(int argc, char* argv[])
C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum)); C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum));
if (frameNum < 256 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW)) if (frameNum < 96 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW))
{ {
setupCam(lookFrom, lookAt, vup); setupCam(lookFrom, lookAt, vup);
C3D_TexBind(0, &prevFrame); C3D_TexBind(0, &prevFrame);

View File

@ -7,25 +7,31 @@
.alias tooclose myconst.zzzz .alias tooclose myconst.zzzz
.alias far myconst.wwww .alias far myconst.wwww
.alias noHit myconst2.yyyy .alias noHit myconst2.yyyy
.alias diffuseID myconst.xxxx
.alias metallicID myconst.yyyy
.consti bounceLoopParams(19, 0, 1, 0) .consti bounceLoopParams(14, 0, 1, 0)
.consti calcSphereLoopParams(3, 0, 1, 0)
; (NUM_SPHERES, 0, 1, 0)
.ivec calcSphereLoopParams
.setb b0 true .setb b0 true
.alias true b0 .alias true b0
; xyz center (in world space) ; xyz center (in world space)
; w radius (in world space) ; w radius (in world space)
.fvec spheres[4] .fvec spheres[25]
; material albedo ; material albedo (xyz)
.fvec sphereColors[4] ; material id (w)
.fvec sphereColors[25]
; material emitted light ; material emitted light (xyz)
.fvec sphereLights[4] ; extra material params (w)
.fvec sphereLights[25]
; random numbers ; random numbers
.fvec rand[20] .fvec rand[15]
.in inOrigin v0 .in inOrigin v0
.in inLowerLeftCorner v1 .in inLowerLeftCorner v1
@ -34,7 +40,6 @@
.in inST v4 .in inST v4
.in inPos v5 .in inPos v5
.in inUV v6 .in inUV v6
.in inRand v7
.out outPos position .out outPos position
.out outUV texcoord0 .out outUV texcoord0
@ -59,10 +64,7 @@
; calculate light bounces ; calculate light bounces
for bounceLoopParams for bounceLoopParams
; setup random numbers for this iteration ; setup random numbers for this iteration
mul r11, rand[aL], inRand mov r11, rand[aL]
dp3 r6.x, r11, r11
rsq r6.x, r6.x
mul r11.xyz, r6.xxx, r11.xyz
; reset max ray distance ; reset max ray distance
mov r4.w, far mov r4.w, far
@ -99,7 +101,22 @@
mov r1.xyz, r5.xyz mov r1.xyz, r5.xyz
; set r2 to new ray direction ; set r2 to new ray direction
call metallic ; try diffuse material
cmp diffuseID.w, eq, eq, r10.w
callc cmp.x, diffuse
jmpc cmp.x, materialFound
; try metallic material
cmp metallicID.w, eq, eq, r10.w
callc cmp.x, metallic
jmpc cmp.x, materialFound
; material doesn't reflect light
; used mostly for light-emitting objects
jmpu true, labl
materialFound:
nop
.end .end
labl: labl:
@ -118,6 +135,7 @@
; Calculate Sphere Intersection ; Calculate Sphere Intersection
; ----------------------------- ; -----------------------------
; Performs a ray-sphere intersection test.
; ;
; Inputs ; Inputs
; ------ ; ------
@ -133,7 +151,9 @@
; ------- ; -------
; r4.w: new min distance ; r4.w: new min distance
; r10.xyz: albedo ; r10.xyz: albedo
; r10.w: material id
; r12.xyz: light emitted ; r12.xyz: light emitted
; r12.w: extra material info
; ;
; Temporaries ; Temporaries
; ----------- ; -----------
@ -222,25 +242,48 @@
rcp r3.w, r3.w rcp r3.w, r3.w
mul r7.xyz, r7.xyz, r3.w mul r7.xyz, r7.xyz, r3.w
; set albedo ; set albedo and material type
mov r10.xyz, sphereColors[aL].xyz mov r10.xyzw, sphereColors[aL].xyzw
; set light emitted ; set light emitted and extra material info
mov r12.xyz, sphereLights[aL].xyz mov r12.xyzw, sphereLights[aL].xyzw
; early exit label ; early exit label
calcSphereExit: calcSphereExit:
nop nop
.end .end
; All Materials
; -------------
; Calculates the new ray direction for a given material.
;
; Inputs
; ------
; r1.xyz: ray origin
; r2.xyz: ray direction
; r3.xyz: sphere origin
; r3.w: sphere radius
; r4.w: min distance
; r11.xyz: random unit vector
; r11.w: random number
;
; Outputs
; -------
; r2.xyz: new ray direction
; Diffuse Material
; ----------------
.proc diffuse .proc diffuse
add r2.xyz, r7.xyz, r11.xyz add r2.xyz, r7.xyz, r11.xyz
.end .end
; Metallic Material
; -----------------
.proc metallic .proc metallic
dp3 r6.xyz, r2, r7 dp3 r6.xyz, r2, r7
mul r6.xyz, twos, r6.xyz mul r6.xyz, twos, r6.xyz
mad r2.xyz, -r6.xyz, r7.xyz, r2.xyz mad r2.xyz, -r6.xyz, r7.xyz, r2.xyz
; add a bit of random "fuzziness" to the metal? ; add a bit of random "fuzziness" to the metal
mad r2.xyz, r11.xyz, r11.w, r2.xyz mad r2.xyz, r11.xyz, r12.w, r2.xyz
.end .end