java - 反射没有正确反射

标签 java colors raytracing depth

我正在编写一个光线追踪器。我目前正在研究反射。但似乎没有正确反射。我不断收到 StackOverflowError。我增加了内存,它现在运行,但反射并不像我想象的那样就这样吧。

What I thought
(来源:ageofarmour.com)

我以为它会反射反射!但结果就是这样。

注意:这是在将法线移离对象并更改颜色计算之后的结果!检查 Cal_Reflection 以了解新的颜色计算!

My Sad Reflections

这是我的跟踪器代码!

public class Tracer {

public boolean Tracing;
public Camera Cam;
public int Width, Height;
public BufferedImage Image;
public Color BackGroundColor;
public int StartX, StartY, EndX, EndY, RowCount, ColCount;
public double AmbientLight;
public double DiffuseLight;
public int MaxReflectionCount;
public ArrayList<GeometricObject> GeoObjects;
public ArrayList<LightObject> LightObjects;

public Tracer(Camera cam, int width, int height, BufferedImage image, Color backGroundColor, int startX, int startY, int endX, int endY, int rowCount, int colCount, double ambientLight, double diffuseLight, int maxReflectionCount, ArrayList<GeometricObject> geoObjects, ArrayList<LightObject> lightObjects) {
    super();
    Cam = cam;
    Width = width;
    Height = height;
    Image = image;
    BackGroundColor = backGroundColor;
    StartX = startX;
    StartY = startY;
    EndX = endX;
    EndY = endY;
    RowCount = rowCount;
    ColCount = colCount;
    AmbientLight = ambientLight;
    DiffuseLight = diffuseLight;
    MaxReflectionCount = maxReflectionCount;
    GeoObjects = geoObjects;
    LightObjects = lightObjects;
}

public void TracePixelFast(int x, int y) {
    Color color = new Color(BackGroundColor.r, BackGroundColor.g, BackGroundColor.b);
    for (int o = 0; o < GeoObjects.size(); o++) {
        GeometricObject GO = GeoObjects.get(o);
        Ray r = new Ray(Cam.GetRayPos(Width, Height, x, y, 1, 1, RowCount, ColCount), Cam.GetRayDir(Width, Height, x, y, 1, 1, RowCount, ColCount));
        double hit = GO.hit(r);
        if (hit != 0.0) {
            color = Cal_Pixel(x, y);
            Image.setRGB(x, y, color.toInt());
            break;
        }
    }
}

public void TracePixelSmooth(int x, int y) {
    Image.setRGB(x, y, Cal_Pixel(x, y).toInt());
}

public Color Cal_Pixel(int x, int y) {
    Color color = new Color(BackGroundColor);
    Color colorh = new Color(BackGroundColor);
    Color bgc = new Color(BackGroundColor);
    int HIT = 0;
    int MISS = 0;
    for (int row = 0; row < RowCount; row++) {
        for (int col = 0; col < ColCount; col++) {
            double min = Double.MAX_VALUE;
            Ray r = new Ray(Cam.GetRayPos(Width, Height, x, y, row, col, RowCount, ColCount), Cam.GetRayDir(Width, Height, x, y, row, col, RowCount, ColCount));
            for (int o = 0; o < GeoObjects.size(); o++) {
                GeometricObject GO = GeoObjects.get(o);
                double hit = GO.hit(r);
                if (hit != 0.0 && hit < min) {
                    min = hit;
                    colorh = ShadePixel(0, GO, r, hit);
                    HIT++;
                } else {
                    double min2 = Double.MAX_VALUE;
                    for (int o2 = 0; o2 < GeoObjects.size(); o2++) {
                        if (o != o2) {
                            GeometricObject GO2 = GeoObjects.get(o2);
                            double hit2 = GO2.hit(r);
                            if (hit2 != 0.0 && hit2 < min2) {
                                min2 = hit2;
                                bgc = ShadePixel(0, GO2, r, hit2);
                            }
                        }
                    }
                    MISS++;
                }
            }
        }
    }
    for (int h = 0; h < HIT; h++) {
        color.Add(colorh);
    }
    for (int m = 0; m < MISS; m++) {
        color.Add(bgc);
    }
    color.Divide(RowCount * ColCount);
    return color;
}

public Color ShadePixel(int ReflectionDepthCount, GeometricObject GO, Ray ray, double t) {
    Normal normal = GO.Cal_Normal(ray, t);
    if (GO.Reflectivity > 0) {
        Color GoColor = new Color(Cal_Reflection(GO, ReflectionDepthCount, ray, normal));
        Color finalcolor = new Color(Cal_Light(GoColor, normal));
        return finalcolor;
    } else {
        ;
        Color finalcolor = new Color(Cal_Light(GO.Color, normal));
        return finalcolor;
    }
}

public Color Cal_Light(Color color, Normal normal) {
    ArrayList<Color> PixelShade = new ArrayList<Color>();
    Color Final = new Color();
    for (int l = 0; l < LightObjects.size(); l++) {
        LightObject light = LightObjects.get(l);
        Vector3D r_Dir = light.Pos.Sub(normal.Origin);
        r_Dir.normalize();
        Ray raytolight = new Ray(normal.Origin, r_Dir);
        int WAS_HIT = 0;
        for (int o = 0; o < GeoObjects.size(); o++) {
            GeometricObject NGO = GeoObjects.get(o);
            double hit = NGO.hit(raytolight);
            if (hit != 0.0) {
                WAS_HIT = 1;
            }
        }
        PixelShade.add(light.ShadePixel(WAS_HIT, normal, r_Dir, color, AmbientLight, DiffuseLight));
    }
    for (int s = 0; s < PixelShade.size(); s++) {
        Final.Add(PixelShade.get(s));
    }
    Final.Divide(PixelShade.size());
    return Final;
}

public Color Cal_Reflection(GeometricObject OriginalObject, int ReflectionDepthCount, Ray InRay, Normal normal) {
    if (ReflectionDepthCount <= MaxReflectionCount) {
        GeometricObject LastGO = null;
        Ray LastRay = null;
        double LastT = 0.0;
        double min = Double.MAX_VALUE;
        Vector3D Origin = normal.Origin.Add(normal.Direction.Mul(1E-100));
        Vector3D Direction = normal.Direction;
        Direction.normalize();
        Ray r = new Ray(Origin, Direction);
        for (int o = 0; o < GeoObjects.size(); o++) {
            GeometricObject GO = GeoObjects.get(o);
            double hit = GO.hit(r);
            if (hit != 0.0 && hit < min) {
                min = hit;
                LastGO = GO;
                LastRay = r;
                LastT = hit;
            }
        }
        if (LastGO != null) {
            System.out.println(ReflectionDepthCount);
            Color Reflected = new Color(ShadePixel(ReflectionDepthCount++, LastGO, LastRay, LastT));
            Color HitColor = new Color(LastGO.Color);
            Color FinalColor = new Color(OriginalObject.Color);
            Reflected.Mul(OriginalObject.Reflectivity);
            HitColor.Mul(OriginalObject.Reflectivity);
            FinalColor.Add(HitColor);
            FinalColor.Add(Reflected);
            FinalColor.Divide(2);
            return FinalColor;
        }
    } else {
        return BackGroundColor;
    }
    return OriginalObject.Color;
}

public void TraceArea(boolean SmoothTracing) {
    Tracing = true;
    if (SmoothTracing) {
        for (int x = StartX; x < EndX; x++) {
            for (int y = StartY; y < EndY; y++) {
                TracePixelSmooth(x, y);
            }
        }
    } else {
        for (int x = StartX; x < EndX; x++) {
            for (int y = StartY; y < EndY; y++) {
                TracePixelFast(x, y);
            }
        }
    }
}}

这是我的球体代码!

public class Sphere extends GeometricObject{

public Vector3D Center;
public double Radius;

public Sphere(Vector3D Center,Color Color,double Radius,double Reflectivity){
    this.Center = Center;
    this.Radius = Radius;
    this.Color = Color;
    this.Reflectivity = Reflectivity;
}

public double hit(Ray ray) {
    double a = ray.Direction.Dot(ray.Direction);
    double b = 2 * ray.Origin.Sub(Center).Dot(ray.Direction);
    double c = ray.Origin.Sub(Center).Dot(ray.Origin.Sub(Center))-Radius*Radius;
    double discreminant = b*b-4*a*c;
    if(discreminant < 0.0f){
        return 0.0;
    }else{
        double t = (-b - Math.sqrt(discreminant))/(2*a);
        if(t > 10E-9){
            return t;
        }else{
            return 0.0;
        }
    }
}

public Normal Cal_Normal(Ray ray,double t) {
    Vector3D NPos = new Vector3D(ray.Origin.x + ray.Direction.x*t,ray.Origin.y + ray.Direction.y*t,ray.Origin.z + ray.Direction.z*t);
    Vector3D NDir = NPos.Sub(Center).Div(Radius);
    NDir.normalize();
    return new Normal(NPos,NDir);
}}

这是我的启动器,用于控制场景和跟踪器!

public class Launcher {
public static int Width = 600;
public static int Height = 600;

public static void main(String[] args) {
    Scene scene = new Scene(Width, Height, 8, 8, new Color(0, 0, 0), new Camera(new Vector3D(0, 0, 30), new Vector3D(0.3, 0, -1), 1, true, Width, Height, 40), 0.1, 0.2, 2);
    // scene.AddObject(new Sphere(new Vector3D(0,0,0),new
    // Color(0,255,0),5,1));
    // scene.AddObject(new Sphere(new Vector3D(-30,0,0),new
    // Color(0,0,255),10,0.5));
    // scene.AddObject(new Sphere(new Vector3D(30,0,0),new
    // Color(255,0,0),10,0.5));
    scene.AddObject(new Sphere(new Vector3D(15, 0, 0), new Color(255, 0, 0), 15, 1));
    scene.AddObject(new Sphere(new Vector3D(-15, 0, 0), new Color(0, 0, 255), 15, 1));
    scene.AddLight(new NonColoredLight(new Vector3D(0, 0, 20), 0.1));
    long Start = System.currentTimeMillis();
    BufferedImage Image = scene.Trace(false, 2);
    long End = System.currentTimeMillis();
    System.out.println("Milli Seconds To Render " + (End - Start));
    File ImageFile = new File("TracedImage.png");
    try {
        ImageIO.write(Image, "PNG", ImageFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
}}

这是场景代码!

public Scene(int width, int height, int row, int col, Color backGroundColor, Camera cam, double ambientLight, double diffuseLight, int maxReflectionCount) {
    super();
    Width = width;
    Height = height;
    Row = row;
    Col = col;
    BackGroundColor = backGroundColor;
    Cam = cam;
    AmbientLight = ambientLight;
    DiffuseLight = diffuseLight;
    MaxReflectionCount = maxReflectionCount;
    GeoObjects = new ArrayList<GeometricObject>();
    LightObjects = new ArrayList<LightObject>();
    if (ambientLight > 1) {
        AmbientLight = 1;
    } else if (ambientLight < 0) {
        AmbientLight = 0;
    } else {
        AmbientLight = ambientLight;
    }
    if (diffuseLight > 1) {
        DiffuseLight = 1;
    } else if (diffuseLight < 0) {
        DiffuseLight = 0;
    } else {
        DiffuseLight = ambientLight;
    }
}

public void AddObject(GeometricObject GO) {
    GeoObjects.add(GO);
}

public void AddLight(LightObject Light) {
    LightObjects.add(Light);
}

public BufferedImage Trace(boolean SmoothTracing, int ThreadCount) {
    Image = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_RGB);

    Tracer tracer = new Tracer(Cam, Width, Height, Image, BackGroundColor, 0, 0, Width, Height, Row, Col, AmbientLight, DiffuseLight, MaxReflectionCount, GeoObjects, LightObjects);
    tracer.TraceArea(SmoothTracing);

    return Image;
}}

如果您需要我发布更多代码,请告诉我!

提前致谢!

第一次反射的变量!

AmbientLight    0.1 
BackGroundColor Color  (id=39)  
    b   0.0 
    g   0.0 
    r   0.0 
Cam Camera  (id=41) 
    Direction   Vector3D  (id=104)  
        x   0.3 
        y   0.0 
        z   -1.0    
    Distance    357.526077778263    
    FOV 40.0    
    Height  600 
    Perspective true    
    PixelSize   1.0 
    Pos Vector3D  (id=115)  
        x   0.0 
        y   0.0 
        z   30.0    
    u   Vector3D  (id=116)  
        x   -0.9578262852211514 
        y   0.0 
        z   -0.28734788556634544    
    v   Vector3D  (id=117)  
        x   0.0 
        y   1.0 
        z   0.0 
    w   Vector3D  (id=118)  
        x   0.2873478855663454  
        y   0.0 
        z   -0.9578262852211513 
    Width   600 
    ColCount    8   
   DiffuseLight 0.1 
   EndX 600 
   EndY 600 
GeoObjects  ArrayList<E>  (id=43)   
    [0] Sphere  (id=26) 
    [1] Sphere  (id=34) 
Height  600 
Image   BufferedImage  (id=50)  
    accelerationPriority    0.5 
    colorModel  DirectColorModel  (id=120)  
    imageType   1   
    osis    null    
    properties  null    
    raster  IntegerInterleavedRaster  (id=124)  
    surfaceManager  null    
LightObjects    ArrayList<E>  (id=59)   
    [0] NonColoredLight  (id=88)    
MaxReflectionCount  2   
RowCount    8   
StartX  0   
StartY  0   
Tracing true    
Width   600 
OriginalObject  Sphere  (id=26) 
Center  Vector3D  (id=60)   
Color   Color  (id=61)  
Radius  15.0    
Reflectivity    1.0 
ReflectionDepthCount    0   
InRay Ray  (id=29)  
Direction   Vector3D  (id=62)   
Origin  Vector3D  (id=63)   
normal Normal  (id=31)  
Direction   Vector3D  (id=38)   
Origin  Vector3D  (id=36)   
LastGO Sphere  (id=34)  
Center  Vector3D  (id=64)   
Color   Color  (id=65)  
Radius  15.0    
Reflectivity    1.0 
LastRay Ray  (id=35)    
Direction   Vector3D  (id=38)   
Origin  Vector3D  (id=36)   
LastT 4.2468950498166125    
min 4.2468950498166125  
Origin Vector3D  (id=36)    
x   0.5809721247344103  
y   -0.023188722729640822   
z   0.8135930637731328  
Direction     Vector3D  (id=38) 
x   -0.32494278056317   
y   -0.02694400302823308    
z   0.9453497818589108  
r     Ray  (id=35)  
Direction   Vector3D  (id=38)   
Origin  Vector3D  (id=36)

Project Zip File

最佳答案

您将光线精确反射到物体表面。当检查与反射光线的交叉点时,您再次击中同一个物体。您假设检查距离是否等于 0.0 就足以避免这种情况,但 FP 数字比您想象的要棘手......

关于java - 反射没有正确反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32785322/

相关文章:

java - 我可以使用什么来代替 "this"作为传递参数?

php - 如何在 php 中为迭代表设置替代行颜色?

excel - 如何将行格式化为按第 1 列中的相似值进行颜色分组

f# - 光线追踪 F# - 缺少三角形会在图 : Hit properly? 中产生孔洞

java - 如何使用java创建远程桌面访问应用程序?

java - 如何将我的容器化项目连接到在本地主机上运行的 kafka?

vba - 选项卡 ColorIndex 重置 excel vba

OpenCL 遍历内核——进一步优化

algorithm - 改组和 NRooks 约束保存

java - Gradle 构建失败,消息为 : TaskDependencyResolveException: Could not determine the dependencies of task ':compileDebugKotlin'