Improved random sample quality

This commit is contained in:
Shylie 2024-04-28 08:27:25 -04:00
parent dceb378111
commit 3b64e9e8aa
2 changed files with 139 additions and 79 deletions

View File

@ -18,6 +18,7 @@ struct vertex
float st[2]; float st[2];
float coords[3]; float coords[3];
float uv[2]; float uv[2];
float rand[3];
}; };
static DVLB_s* vshaderDVLB; static DVLB_s* vshaderDVLB;
@ -26,9 +27,10 @@ static s8 spheresUniformLocation;
static s8 sphereColorsUniformLocation; static s8 sphereColorsUniformLocation;
static s8 sphereLightsUniformLocation; static s8 sphereLightsUniformLocation;
static s8 randUniformLocation; static s8 randUniformLocation;
static s8 sampleRandUniformLocation;
static s8 calcSphereLoopParamsUniformLocation; static s8 calcSphereLoopParamsUniformLocation;
static constexpr unsigned int VERTEX_COUNT_W = 150; static constexpr unsigned int VERTEX_COUNT_W = 50;
static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6; static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6;
static constexpr unsigned int VERTEX_COUNT = VERTEX_COUNT_W * VERTEX_COUNT_H; static constexpr unsigned int VERTEX_COUNT = VERTEX_COUNT_W * VERTEX_COUNT_H;
static constexpr unsigned int INDICES_COUNT = (VERTEX_COUNT * 2 + VERTEX_COUNT_H * 2); static constexpr unsigned int INDICES_COUNT = (VERTEX_COUNT * 2 + VERTEX_COUNT_H * 2);
@ -135,6 +137,11 @@ static void setupVertices()
v.uv[0] = s * (240.0f / 256.0f); v.uv[0] = s * (240.0f / 256.0f);
v.uv[1] = t * (400.0f / 512.0f); v.uv[1] = t * (400.0f / 512.0f);
const C3D_FVec r = randvec();
v.rand[0] = r.x;
v.rand[1] = r.y;
v.rand[2] = r.z;
} }
} }
@ -143,12 +150,19 @@ static void setupVertices()
static void setupRandom() static void setupRandom()
{ {
constexpr int NUM_RAND = 15; // needs to be the same as rand array length in vshader.v.pica constexpr int NUM_RAND = 10; // 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();
} }
constexpr int NUM_SAMPLE_RAND = 2;
C3D_FVec* sampleRandPtr = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sampleRandUniformLocation, NUM_SAMPLE_RAND);
for (int i = 0; i < NUM_SAMPLE_RAND; i++)
{
sampleRandPtr[i] = randvec();
}
} }
static void sceneInit() static void sceneInit()
@ -178,6 +192,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");
sampleRandUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sampleRand");
calcSphereLoopParamsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "calcSphereLoopParams"); calcSphereLoopParamsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "calcSphereLoopParams");
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
@ -189,13 +204,14 @@ 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, 3);
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), 3, 0x654); BufInfo_Add(bufInfo, vboData, sizeof(vertex), 4, 0x7654);
C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env); C3D_TexEnvInit(env);
@ -203,7 +219,7 @@ static void sceneInit()
C3D_TexEnvFunc(env, C3D_RGB, GPU_INTERPOLATE); C3D_TexEnvFunc(env, C3D_RGB, GPU_INTERPOLATE);
C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE); C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
constexpr u16 NUM_SPHERES = 4; constexpr u16 NUM_SPHERES = 5;
C3D_IVUnifSet(GPU_VERTEX_SHADER, calcSphereLoopParamsUniformLocation, NUM_SPHERES - 1, 0, 1, 0); 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);
@ -211,18 +227,21 @@ static void sceneInit()
spheres[1] = FVec4_New(0.6f, 0.0f, 0.0f, 0.5f); spheres[1] = FVec4_New(0.6f, 0.0f, 0.0f, 0.5f);
spheres[2] = FVec4_New(-0.6f, 0.0f, 0.0f, 0.5f); spheres[2] = FVec4_New(-0.6f, 0.0f, 0.0f, 0.5f);
spheres[3] = FVec4_New(0.0f, 10.0f, 0.0f, 9.0f); spheres[3] = FVec4_New(0.0f, 10.0f, 0.0f, 9.0f);
spheres[4] = FVec4_New(0.0f, 0.4f, 0.0f, 0.2f);
C3D_FVec* sphereColors = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereColorsUniformLocation, NUM_SPHERES); C3D_FVec* sphereColors = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereColorsUniformLocation, NUM_SPHERES);
sphereColors[0] = FVec4_New(0.9f, 0.3f, 0.3f, 0); sphereColors[0] = FVec4_New(0.9f, 0.3f, 0.3f, 0);
sphereColors[1] = FVec4_New(0.3f, 0.9f, 0.3f, 1); sphereColors[1] = FVec4_New(0.3f, 0.9f, 0.3f, 1);
sphereColors[2] = FVec4_New(0.3f, 0.3f, 0.9f, 0); sphereColors[2] = FVec4_New(0.3f, 0.3f, 0.9f, 0);
sphereColors[3] = FVec4_New(1.0f, 1.0f, 1.0f, -1); sphereColors[3] = FVec4_New(1.0f, 1.0f, 1.0f, -1);
sphereColors[4] = FVec4_New(0.8f, 0.6f, 0.1f, 2);
C3D_FVec* sphereLights = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereLightsUniformLocation, NUM_SPHERES); C3D_FVec* sphereLights = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereLightsUniformLocation, NUM_SPHERES);
sphereLights[0] = FVec4_New(0.0f, 0.0f, 0.0f, 0); sphereLights[0] = FVec4_New(0.0f, 0.0f, 0.0f, 0);
sphereLights[1] = FVec4_New(0.0f, 0.0f, 0.0f, 0.2f); sphereLights[1] = FVec4_New(0.0f, 0.0f, 0.0f, 0.2f);
sphereLights[2] = FVec4_New(0.0f, 0.0f, 0.0f, 0); sphereLights[2] = FVec4_New(0.0f, 0.0f, 0.0f, 0);
sphereLights[3] = FVec4_New(0.5f, 0.5f, 0.5f, 0); sphereLights[3] = FVec4_New(2.5f, 2.5f, 2.5f, 0);
sphereLights[4] = FVec4_New(0.0f, 0.0f, 0.0f, 0);
} }
static void sceneRender() static void sceneRender()
@ -276,9 +295,9 @@ int main(int argc, char* argv[])
sceneInit(); sceneInit();
C3D_FVec lookFrom = FVec3_New(0, 0.0f, 1.0f); C3D_FVec lookFrom = FVec3_New(0.0f, 0.0f, 1.0f);
C3D_FVec lookAt = FVec3_New(0, 0, 0.0f); C3D_FVec lookAt = FVec3_New(0.0f, 0.0f, 0.0f);
C3D_FVec vup = FVec3_New(0, 1.0f, 0); C3D_FVec vup = FVec3_New(0.0f, 1.0f, 0.0f);
bool dirty = true; bool dirty = true;
unsigned int frameNum = 0; unsigned int frameNum = 0;
@ -346,10 +365,10 @@ int main(int argc, char* argv[])
setupVertices(); setupVertices();
setupRandom(); setupRandom();
C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum)); if (frameNum < 32 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW))
if (frameNum < 96 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW))
{ {
C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum));
setupCam(lookFrom, lookAt, vup); setupCam(lookFrom, lookAt, vup);
C3D_TexBind(0, &prevFrame); C3D_TexBind(0, &prevFrame);
C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0, 0); C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0, 0);
@ -366,6 +385,8 @@ int main(int argc, char* argv[])
frameNum++; frameNum++;
} }
C3D_TexEnvColor(C3D_GetTexEnv(0), 0);
} }
sceneExit(); sceneExit();

View File

@ -1,5 +1,6 @@
.constf myconst(0.0, 1.0, 0.001, 1000.0) .constf myconst(0.0, 1.0, 0.001, 1000.0)
.constf myconst2(0.5, 999.0, 1.1, 2.0) .constf myconst2(0.5, 999.0, 1.1, 2.0)
.constf myconst3(0.5, 0.0, 0.0, 0.0)
.alias zeros myconst.xxxx .alias zeros myconst.xxxx
.alias halfs myconst2.xxxx .alias halfs myconst2.xxxx
.alias ones myconst.yyyy .alias ones myconst.yyyy
@ -7,10 +8,14 @@
.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 samplesRCP myconst3.xxxx
.alias diffuseID myconst.xxxx .alias diffuseID myconst.xxxx
.alias metallicID myconst.yyyy .alias metallicID myconst.yyyy
.alias dielectricID myconst2.wwww
.consti bounceLoopParams(14, 0, 1, 0) .consti sampleLoopParams(4, 0, 1, 0)
.consti bounceLoopParams(9, 0, 1, 0)
; (NUM_SPHERES, 0, 1, 0) ; (NUM_SPHERES, 0, 1, 0)
.ivec calcSphereLoopParams .ivec calcSphereLoopParams
@ -31,7 +36,8 @@
.fvec sphereLights[25] .fvec sphereLights[25]
; random numbers ; random numbers
.fvec rand[15] .fvec rand[10]
.fvec sampleRand[5]
.in inOrigin v0 .in inOrigin v0
.in inLowerLeftCorner v1 .in inLowerLeftCorner v1
@ -40,89 +46,109 @@
.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
.out outColor color .out outColor color
.proc main .proc main
; r1 = inOrigin mov r15.xyz, zeros
mov r1, inOrigin
; r2 = inDirection for sampleLoopParams
mov r2.xyz, inLowerLeftCorner ; r1 = inOrigin
mov r3.xy, inST.xy mov r1, inOrigin
mad r2.xyz, inHorizontal, r3.x, r2.xyz
mad r2.xyz, inVertical, r3.y, r2.xyz
; set initial color multiplier to (1, 1, 1) ; r2 = inDirection
mov r4.xyz, ones mov r2.xyz, inLowerLeftCorner
mov r3.xy, inST.xy
mad r2.xyz, inHorizontal, r3.x, r2.xyz
mad r2.xyz, inVertical, r3.y, r2.xyz
; set initial color to (0, 0, 0) ; set initial color multiplier to (1, 1, 1)
mov r13.xyz, zeros mov r4.xyz, ones
; calculate light bounces ; set initial color to (0, 0, 0)
for bounceLoopParams mov r13.xyz, zeros
; setup random numbers for this iteration
mov r11, rand[aL]
; reset max ray distance mov r14.xyz, sampleRand[aL].xyz
mov r4.w, far
; set albedo to a large number for sphere hit check ; calculate light bounces
mov r10.xyz, far for bounceLoopParams
; setup random numbers for this iteration
mov r11, rand[aL]
add r11.xyz, r11.xyz, r14.xyz
add r11.xyz, r11.xyz, inRand.xyz
dp3 r14.w, r11.xyz, r11.xyz
rsq r14.w, r14.w
mul r11.xyz, r11.xyz, r14.w
; for each sphere ; reset max ray distance
for calcSphereLoopParams mov r4.w, far
; r3 = spheres[i]
mov r3, spheres[aL] ; set albedo to a large number for sphere hit check
mov r10.xyz, far
; for each sphere
for calcSphereLoopParams
; r3 = spheres[i]
mov r3, spheres[aL]
; do calculation ; do calculation
call calcSphere call calcSphere
.end
; check if noHit < albedo
; and exit early if true
; as albedo has not been set
; after the initial set
; which only happens when
; a ray does not hit any spheres
cmp noHit.xyz, lt, lt, r10.xyz
; not using breakc. it behaves weird.
jmpc cmp.x, labl
; multiply color by albedo
mul r4.xyz, r4.xyz, r10.xyz
; add emitted light
mad r13.xyz, r4.xyz, r12.xyz, r13.xyz
; set r1 to new ray origin
mov r1.xyz, r5.xyz
; set r2 to new ray direction
; 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
; try dielectric material
cmp dielectricID.w, eq, eq, r10.w
callc cmp.x, dielectric
jmpc cmp.x, materialFound
; material doesn't reflect light
; used mostly for light-emitting objects
jmpu true, labl
materialFound:
nop
.end .end
; check if noHit < albedo labl:
; and exit early if true
; as albedo has not been set
; after the initial set
; which only happens when
; a ray does not hit any spheres
cmp noHit.xyz, lt, lt, r10.xyz
; not using breakc. it behaves weird.
jmpc cmp.x, labl
; multiply color by albedo ; add final color to output
mul r4.xyz, r4.xyz, r10.xyz add r15.xyz, r13.xyz, r15.xyz
; add emitted light
mad r13.xyz, r4.xyz, r12.xyz, r13.xyz
; set r1 to new ray origin
mov r1.xyz, r5.xyz
; set r2 to new ray direction
; 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: ; divide by sample count
mul outColor.xyz, samplesRCP, r15.xyz
; copy final color to output
mov outColor.xyz, r13.xyz
; set alpha to 1 ; set alpha to 1
mov outColor.w, ones mov outColor.w, ones
@ -133,6 +159,7 @@
end end
.end .end
; -----------------------------
; Calculate Sphere Intersection ; Calculate Sphere Intersection
; ----------------------------- ; -----------------------------
; Performs a ray-sphere intersection test. ; Performs a ray-sphere intersection test.
@ -159,6 +186,7 @@
; ----------- ; -----------
; r5.xyz: new origin ; r5.xyz: new origin
; r7.xyz: hit normal ; r7.xyz: hit normal
; r7.w: ray is outside sphere (1) or inside sphere (0)
; r8.xyzw: used for calculations ; r8.xyzw: used for calculations
; r9.xyzw: used for calculations ; r9.xyzw: used for calculations
@ -253,8 +281,9 @@
nop nop
.end .end
; All Materials ; ---------
; ------------- ; Materials
; ---------
; Calculates the new ray direction for a given material. ; Calculates the new ray direction for a given material.
; ;
; Inputs ; Inputs
@ -274,16 +303,26 @@
; Diffuse Material ; Diffuse Material
; ---------------- ; ----------------
.proc diffuse .proc diffuse
add r2.xyz, r7.xyz, r11.xyz add r2.xyz, r7.xyz, r11.xyz
.end .end
; Metallic Material ; 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, r12.w, r2.xyz mad r2.xyz, r11.xyz, r12.w, r2.xyz
.end
; Dielectric Material
; -------------------
.proc dielectric
; currently diffuse material, implement fr later
add r2.xyz, r7.xyz, r11.xyz
.end .end