void canvasTest(const TPixels32Ref& ctx) { if (ctx.getIsEmpty()) return; long w = ctx.width; long h = ctx.height; ctx.fillColor(Color32(0, 0, 0, 0)); Color32* pixels = ctx.pdata; for (long y = 0; y < h; ++y){ for (long x = 0; x < w; ++x){ pixels[x].r = (UInt8)(x * 255 / w); pixels[x].g = (UInt8)(y * 255 / h); pixels[x].b = 0; pixels[x].a = 255; } (UInt8*&)pixels += ctx.byte_width; } }
void renderDepth(const TPixels32Ref& ctx) { if (ctx.getIsEmpty()) return; Union scene; scene.push(new Sphere(Vector3(0, 10, -10), 10)); scene.push(new Plane(Vector3(0, 1, 0), 0)); PerspectiveCamera camera(Vector3(0, 10, 10), Vector3(0, 0, -1), Vector3(0, 1, 0), 90); long maxDepth = 20; long w = ctx.width; long h = ctx.height; ctx.fillColor(Color32(0, 0, 0, 0)); Color32* pixels = ctx.pdata; scene.initialize(); camera.initialize(); float dx = 1.0f / w; float dy = 1.0f / h; float dD = 255.0f / maxDepth; for (long y = 0; y < h; ++y){ float sy = 1 - dy*y; for (long x = 0; x < w; ++x){ float sx = dx*x; Ray3 ray(camera.generateRay(sx, sy)); IntersectResult result = scene.intersect(ray); if (result.geometry) { UInt8 depth = (UInt8)(255 - std::min(result.distance*dD, 255.0f)); pixels[x].r = depth; pixels[x].g = depth; pixels[x].b = depth; pixels[x].a = 255; } } (UInt8*&)pixels += ctx.byte_width; } }
void renderNormal(const TPixels32Ref& ctx) { if (ctx.getIsEmpty()) return; Sphere scene(Vector3(0, 10, -10), 10); PerspectiveCamera camera(Vector3(0, 10, 10), Vector3(0, 0, -1), Vector3(0, 1, 0), 90); long maxDepth = 20; long w = ctx.width; long h = ctx.height; ctx.fillColor(Color32(0, 0, 0, 0)); Color32* pixels = ctx.pdata; scene.initialize(); camera.initialize(); float dx = 1.0f / w; float dy = 1.0f / h; float dD = 255.0f / maxDepth; for (long y = 0; y < h; ++y){ float sy = 1 - dy*y; for (long x = 0; x < w; ++x){ float sx = dx*x; Ray3 ray(camera.generateRay(sx, sy)); IntersectResult result = scene.intersect(ray); if (result.geometry) { pixels[x].r = (UInt8)((result.normal.x + 1) * 128); pixels[x].g = (UInt8)((result.normal.y + 1) * 128); pixels[x].b = (UInt8)((result.normal.z + 1) * 128); pixels[x].a = 255; } } (UInt8*&)pixels += ctx.byte_width; } }
void rayTrace(const TPixels32Ref& ctx) { if (ctx.getIsEmpty()) return; Plane* plane = new Plane(Vector3(0, 1, 0), 0); Sphere* sphere1 = new Sphere(Vector3(-10, 10, -10), 10); Sphere* sphere2 = new Sphere(Vector3(10, 10, -10), 10); plane->material = new CheckerMaterial(0.1f); sphere1->material = new PhongMaterial(Color::red(), Color::white(), 16); sphere2->material = new PhongMaterial(Color::blue(), Color::white(), 16); Union scene; scene.push(plane); scene.push(sphere1); scene.push(sphere2); PerspectiveCamera camera(Vector3(0, 5, 15), Vector3(0, 0, -1), Vector3(0, 1, 0), 90); long w = ctx.width; long h = ctx.height; ctx.fillColor(Color32(0, 0, 0, 0)); Color32* pixels = ctx.pdata; scene.initialize(); camera.initialize(); float dx = 1.0f / w; float dy = 1.0f / h; for (long y = 0; y < h; ++y){ float sy = 1 - dy*y; for (long x = 0; x < w; ++x){ float sx = dx*x; Ray3 ray(camera.generateRay(sx, sy)); IntersectResult result = scene.intersect(ray); if (result.geometry) { Color color = result.geometry->material->sample(ray, result.position, result.normal); color.saturate(); pixels[x].r = (UInt8)(color.r * 255); pixels[x].g = (UInt8)(color.g * 255); pixels[x].b = (UInt8)(color.b * 255); pixels[x].a = 255; } } (UInt8*&)pixels += ctx.byte_width; } }
Color rayTraceRecursive(IGeometry* scene, const Ray3& ray, long maxReflect) { IntersectResult result = scene->intersect(ray); if (result.geometry){ float reflectiveness = result.geometry->material->reflectiveness; Color color = result.geometry->material->sample(ray, result.position, result.normal); color = color.multiply(1 - reflectiveness); if ((reflectiveness > 0) && (maxReflect > 0)) { Vector3 r = result.normal.multiply(-2 * result.normal.dot(ray.direction)).add(ray.direction); Ray3 ray = Ray3(result.position, r); Color reflectedColor = rayTraceRecursive(scene, ray, maxReflect - 1); color = color.add(reflectedColor.multiply(reflectiveness)); } return color; } else return Color::black(); } void rayTraceRecursive(const TPixels32Ref& ctx) { if (ctx.getIsEmpty()) return; Plane* plane = new Plane(Vector3(0, 1, 0), 0); Sphere* sphere1 = new Sphere(Vector3(-10, 10, -10), 10); Sphere* sphere2 = new Sphere(Vector3(10, 10, -10), 10); plane->material = new CheckerMaterial(0.1f, 0.5); sphere1->material = new PhongMaterial(Color::red(), Color::white(), 16, 0.25); sphere2->material = new PhongMaterial(Color::blue(), Color::white(), 16, 0.25); Union scene; scene.push(plane); scene.push(sphere1); scene.push(sphere2); PerspectiveCamera camera(Vector3(0, 5, 15), Vector3(0, 0, -1), Vector3(0, 1, 0), 90); long maxReflect = 3; long w = ctx.width; long h = ctx.height; ctx.fillColor(Color32(0, 0, 0, 0)); Color32* pixels = ctx.pdata; scene.initialize(); camera.initialize(); float dx = 1.0f / w; float dy = 1.0f / h; for (long y = 0; y < h; ++y){ float sy = 1 - dy*y; for (long x = 0; x < w; ++x){ float sx = dx*x; Ray3 ray(camera.generateRay(sx, sy)); Color color = rayTraceRecursive(&scene, ray, maxReflect); color.saturate(); pixels[x].r = (UInt8)(color.r * 255); pixels[x].g = (UInt8)(color.g * 255); pixels[x].b = (UInt8)(color.b * 255); pixels[x].a = 255; } (UInt8*&)pixels += ctx.byte_width; } }
主函数实现测试:
int main(){ std::cout << " 请输入回车键开始测试(可以把进程优先级设置为“实时”)> "; waitInputChar(); std::cout << std::endl; test("canvasTest", canvasTest, 2000); test("renderDepth", renderDepth, 100); test("renderNormal", renderNormal, 200); test("rayTrace", rayTrace, 50); test("rayTraceRecursive", rayTraceRecursive, 50); std::cout << std::endl << " 测试完成. "; waitInputChar(); return 0; }