这是一个几年前用c++实现的光线追踪渲染器,使用cpu多线程计算,没有使用任何gpu加速。最后画面的呈现也是使用的gdi绘制,没有使用d3d或ogl。不同于某些基于shader的光线追踪限制性太大,对于通用模型的支持不好(只支持一些标准集合体,且模型都是通过算法产生的)。本渲染器可以支持通用模型的渲染。

光线追踪渲染框架下可以很容易的实现反射、折射、阴影、环境光遮蔽等。不同于传统的3D渲染管线,光线追踪逐个像素计算关照没有光栅化这一步,之前实现过一个软3D渲染管线,光栅化是主要的性能瓶颈。相信随着电脑算力的提高若干年后光线追踪渲染框架将会取代传统的3D管线,不止是渲染效果上更好,当模型面数达到足够数量级时,效率上也会超过传统管线。

本光线追踪渲染器实现了几种基本图元 sphere、box、quad、triangle、billboard。公告板图元是特有的,计算射线追踪时使用的是球形碰撞,取纹理时使用的是面向射线的公告板,阴影还有些问题(树根没对齐)。

三角形图元是最通用的图元,可以配合各类3d建模软件的导出模型。效率上还没优化到实时的地步。有可能目前的cpu算力还做不到实时。使用gpu可能会快一些,下一步可以试试cuda等通用gpu计算。

优化方案:

方案一, 使用bsp加速射线追踪检测,虽然提出效率是log的,但是面多了后还是不够快。

方案二, 以摄像机位置为原点,使用经纬度划分空间分割来加速检测,然后将屏幕分成小块绘制,一个小块只需要做一次剔除(仅初次追踪,镜面体反射后就不行了)可以极快的加速,缺点是当原点附近有大量三角形时效率急速变低。

方案三, 体素分割加速检测,由近到远遍历射线穿过的体素也方便即时返回,测试下来体素分割速度更快一些。

核心源码:

#pragma once
#include <windows.h>#include "Mathlib.h"//Phong shading。  光照=环境光+漫反射+高光class TraceRes;
class Frustum;
class LaCone3Partion;
class UniformVoxelPartion;
class AnguleBoxPartion;
class RayTraceTexture;//根据形状划分 保存在个位
enum PrimitiveType
{//PT_Point,//PT_Line,//PT_Circle, //圆面PT_Sphere = 0,PT_Ellipsoid,PT_Trigon,PT_Quad,PT_Sylinder,PT_Billboard,
};//根据属性划分 保存在十位
enum PrimitiveType2
{PT_Mesh = 0,//面片PT_Light,   //光源PT_Stencil, //蒙版图元,射线击中后执行操作 比如skip ,或者未击中skip。
};enum CullFace
{CF_None,CF_All,CF_Front,CF_Back,
};enum FILTER
{Nearest=0,  Bilinear, ANISOTROPIC,
};//光线追踪没有光栅化,不好确定是放大滤波还是缩小滤波
//SAMP_MAGFILTER,
//SAMP_MINFILTER, #define MaxPrimitive  4096
#define MaxThread 4
//不要虚函数 效率比较低
class Primitive
{
public:Primitive(PrimitiveType primitiveType);virtual ~Primitive(){};//仅拷贝void SetColorTexture(const vec3 &color, RayTraceTexture *texture);//计算了ODEtavoid SetRefleract(float reflection = 0.0f, float refraction = 0.0f, float Eta = 1.0f,RayTraceTexture* tex=NULL);//比switch(primitiveType)慢//virtual bool Intersect(vec3 &rayPos, const vec3 &rayDir, float maxDistance){return false;};public:PrimitiveType primitiveType;RayTraceTexture *pTexture;//折射率保存在贴图中? 保存在普通的alpha通道一个char内容不下? 折射 反射 折射率RayTraceTexture *refleraTexture;bool  visible;CullFace  cullface;float reflection; //反射系数float refraction; //折射系数float Eta, ODEta; //折射率 及其倒数   简单的半透明图元或叠加高亮图元通过折射率0来模拟vec3  color;////float lastDepth[18];  //缓存和上一个像素射线碰撞点的深度,很大的几率变化不大,用于快速排除 ?每个递归深度缓存一个  每线程单独缓存一份char  tag[MaxThread];//void* data;     //比如保存一个light光源指针?//包围球vec3  center;float radius;//包围盒AABB2 aabb;//todo 裁剪体 面 球 或box 限制交点在球或box的内或外才算碰撞,或在面的某一侧,?使用折射贴图跟快更灵活int laYIndexMax;int laYIndexMin;int laXIndexMax;int laXIndexMin;int laZIndexMax;int laZIndexMin;int loIndexMax1[6];int loIndexMin1[6];int loIndexMax2[6];int loIndexMin2[6];
};class TrigonPrim:public Primitive
{
public:TrigonPrim();void SetPos(const vec3 &ptA, const vec3 &ptB, const vec3 &ptC);void SetPos(const vec3 &ptA, const vec3 &ptB, const vec3 &ptC,const vec3& nA,const vec3& nB,const vec3& nC);bool Inside(float x, float y, float z);bool Inside(const vec3 &point);//相交测试中进行alpha测试 缺点:不是最近点的图元没必要浪费alpha测试时间,最近图元不镂空部分也没必要alpha测试//                        优点:减少多加的追踪深度bool Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance);void CalBound();//todo 多返回一个折射率贴图void SampleTexColor(const vec3&pos,vec3&texColor,vec3&refleraColor,FILTER filter);void SampleNormal(const vec3&pos,vec3& normal);public:vec3  ptA, ptB, ptC;//顶点vec2  texA,texB,texC;//纹理坐标vec3  nA,nB,nC;      //法线 高洛德着色,不插值反射面会断开,插值的话正好平滑过渡vec3  dirAB, dirBC, dirCA; //边向量 注意后面两个有用到 dirAB指针++形式用到float lab, lbc, lca;vec3  N;          //面法线float D;vec3  N1, N2, N3; //边面法线float D1, D2, D3;/**/vec3  fa, fb, fc; //投射到摄像机空间远裁剪面上的四个顶点//纹理插值float kVal[2];vec3  B_C,A_C; bool  bLineXY;//xy 平面投影是否共线Polygon2D m_polygon;
};class QuadPrim:public Primitive
{
public:QuadPrim();void SetPos(const vec3 &ptA, const vec3 &ptB, const vec3 &ptC, const vec3 &ptD);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance);bool Inside(vec3 &point);void CalBound();void SampleTexColor(const vec3&pos,vec3&texColor,vec3&refleraColor,FILTER filter);public:vec3  ptA, ptB, ptC, ptD; //顶点vec2  texA,texB,texC,texD;//纹理坐标vec3  B_A, D_A;     //边向量vec3  m;          //重心vec3  dirAB, B, O;float odDisAB,odDisAC;vec3  N;          //面法线float D;vec3  N1, N2, N3, N4;//边面法线float D1, D2, D3, D4;/*D CA B*/vec3  fa, fb, fc, fd; //投射到摄像机空间远裁剪面上的四个顶点Polygon2D m_polygon;};//
class SpherePrim:public Primitive
{
public:SpherePrim();void SetPos(const vec3 &Position, float Radius);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance);bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance);void CalBound();public:float Radius2, ODRadius;};//class SylinderPrim:public Primitive
//{
//public:
//  SylinderPrim();
//  void SetPos(const vec3 &Position, float Radius);
//
//  bool Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes);
//  bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point);
//  bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance);
//  bool Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance);
//  ///** 检测是否与圆柱体碰撞 */
//  //int TestIntersionCylinder(const vec3& position,const vec3& direction, double& lamda, vec3& pNormal,vec3& newposition)
//  //{
//  //  vec3 RC;
//  //  double d;
//  //  double t,s;
//  //  vec3 n,D,O;
//  //  double ln;
//  //  double in,out;
//  //  vec3::subtract(position,cylinder._Position,RC);
//  //  vec3::cross(direction,cylinder._Axis,n);
//  //  ln = n.mag();
//  //  if ( (ln<ZERO)&&(ln>-ZERO) ) return 0;
//  //  n.unit();
//  //  d =  fabs( RC.dot(n) );
//  //  if (d <= cylinder._Radius)
//  //  {
//  //      vec3::cross(RC,cylinder._Axis,O);
//  //      t =  - O.dot(n)/ln;
//  //      vec3::cross(n,cylinder._Axis,O);
//  //      O.unit();
//  //      s =  fabs( sqrt(cylinder._Radius*cylinder._Radius - d*d) / direction.dot(O) );
//
//  //      in = t-s;
//  //      out = t+s;
//
//  //      if (in<-ZERO){
//  //          if (out<-ZERO) return 0;
//  //          else lamda = out;
//  //      }
//  //      else
//  //          if (out<-ZERO) {
//  //              lamda = in;
//  //          }
//  //          else
//  //              if (in<out) lamda = in;
//  //              else lamda = out;
//
//  //              newposition = position+direction*lamda;
//  //              vec3 HB = newposition-cylinder._Position;
//  //              pNormal = HB - cylinder._Axis*(HB.dot(cylinder._Axis));
//  //              pNormal.unit();
//
//  //              return 1;
//  //  }
//  //  return 0;
//  //}
//
//
//  void CalBound();
//
//public:
//  float Radius2, ODRadius;
//
//  vec3 _Axis;
//  //vec3 _Position;
//  //double _Radius;
//};//class BillboardPrim:public QuadPrim
//{
//public:
//  BillboardPrim();
//public:
//  //没检测一次射线都生成新的四个顶点 法线等
//  QuadPrim m_originQuad;
//};//
class BillboardPrim:public SpherePrim
{
public:BillboardPrim();//相交测试中进行alpha测试 缺点:不是最近点的图元没必要浪费alpha测试时间,最近图元不镂空部分也没必要alpha测试//                        优点:减少多加的追踪深度
public://使用对称的球形碰撞,仅仅是纹理坐标计算有些许差别
};//
class LightRT
{
public:LightRT();~LightRT();void Update();public:float Ambient, Diffuse;float ConstantAttenuation, LinearAttenuation, QuadraticAttenuation;SpherePrim *Sphere;QuadPrim   *Quad;//平行光 分割使用体素或光柱分割//LaCone3Partion *m_laConePartion;todo 异形发光体  ,光源颜色和图元颜色图元纹理混合作为最终的光源颜色,另外还具有灯光的方向衰减等普通属性//意义?:发光体表现可以通过叠加高亮模拟假象, 异形发光体的真正意义需要计算射线可追踪到的光源区域大小,来生成柔和的阴影边缘? 无影灯?////int m_quadsCount;//int m_spheresCount;//int m_lightsCount;//灯光图元 可以和普通的场景各种类型图元混合一起划分在一个空间树中,这样碰撞检测效率提高2~3倍,但是带来逻辑混乱?//灯光图元 必须另外单独划分一颗空间树,以便阴影检测时提高效率
};//
class TraceRes
{
public:TraceRes();
public:float distanceSofar;float testDistance;vec3  color, point, testPoint;int   traceDepth;Primitive *primitive;LightRT    *light;vec3  rayPos;vec3  rayDir;
};class PrimitiveBspTree;
class RayTracerThread;class Presenter
{
public:virtual void Present(int scrWidth,int scrHeight,BYTE* colorBuf)=0{};
protected:int  m_wndWidth;int  m_wndHeight;int  m_softBuffWidth;int  m_softBuffHeight;
};//
class RayTraceRendDriver
{
public:RayTraceRendDriver();virtual ~RayTraceRendDriver();virtual bool Init();virtual void Close();virtual void OnSize(int Width, int Height);void        SetPresenter(Presenter* presenter);//!参数设置bool SetSamples(int Samples);int  GetSamples();bool SetQuality(float quality);public://!添加删除图元void CheckPrimitiveVolume(int addCount=1);void AddPrimitives(Primitive* pprimitives,int count);void AddPrimitives(Primitive** pprimitives,int count);void RemovePrimitives(Primitive* pprimitives,int count);void RemovePrimitives(Primitive** pprimitives,int count);//!绘制void ClearColorBuffer();void Render();void RenderRect(int x,int y,int xend,int yend,int threadIndex);void AfterEffectHDR();void Present();////void        DrawPoint(int x, int y);//void      DrawLine(int x1, int y1, int x2, int y2);//void     DrawRect(const RectF& tar); bool        DrawTextureRect(const RectF& tar);//!分割准备//void GenFrustumCell(int frustumSize,int x,int y,int cellX,int cellY,int cellXEnd,int cellYEnd,Frustum&res);//void PreparePartionWithFrustum();void CalRat();//!分割图元void PartionWithBsp(PrimitiveBspTree* bspPartion);//void PartionWithLaLo(laLoPartion *laLoPartion);void PartionWithLaCone(LaCone3Partion *laConePartion);void PartionWithVoxel(UniformVoxelPartion* voxelPartion);void PartionWithAnguleBox(AnguleBoxPartion *anguleBoxPartion);//!标记图元  没有添加,const Primitive* except//void TagWithFrustumLaCone(int cellX,int cellY,int cellXEnd,int cellYEnd);//void TagWithFrustum(Frustum& frustum);void TagWithBsp(const vec3&pos,const vec3&dir);void DumpPrimitives(Primitive** pprimitives,int count);//private://!总光照计算void IlluminatePoint(const Primitive *except, const vec3 &point, const vec3 &normal, vec3 &color,int threadindex);//!单光源密度vec3 LightIntensity(const Primitive *except, const vec3 &point, const vec3 &normal, const vec3 &lightPos, LightRT *light, float AO,int threadindex);//!测试阴影bool TraceShadow(const Primitive *except, const vec3 &lightPos, const vec3 &lightDir, float lightDis,int threadindex);//!环境遮蔽float AmbientOcclusionFactor(const Primitive *except, const vec3 &point, const vec3 &normal,int threadindex);//主投射vec3  TraceRay(const vec3 &rayPos, const vec3 &rayDir, int depth, Primitive *except,int threadindex);public:int MaxTraceDepth;//8 //2//private:Presenter *m_presenter;//BYTE *m_colorBuffer;vec3 *m_hdrColorBuffer;//0.01s并行时间不值得? 输入卡,双缓存需延后处理 一样卡//双缓加速 gdi paint 的同时,追踪不打断,要注意使用双缓冲时可能在追踪过程中接到onsize类消息或者camera改变消息,都需延后处理?//BYTE *m_colorBuffer01;//vec3 *m_hdrColorBuffer01;//BYTE *m_colorBuffer02;//vec3 *m_hdrColorBuffer02;int m_backbufWidth;int m_backbufHeight;int m_wndWidth;int m_wndHeight;float FarPlainDis;int SamplesPerPixel;//1*1 2*2 3*3//全局光照采样次数 辐射度 环境遮蔽int GISampleNum;float ODGISamples;int   WidthMSamples, HeightMSamples, WidthXHeightXSamplesSq;float ODSamples,ODSamplesSq;float AmbientOcclusionIntensity, ODGISamplesXAmbientOcclusionIntensity;//protected:
public://不能单独分开primitive buff obj,这样不利于优化? 区分静态和动态buff也不利?LightRT     *m_lights;int m_lightsCount;Primitive **m_primitives;int m_primitivesCount;int m_primitivesVolume;public:bool m_enableTexture2D;bool m_enableShadow;bool m_enableSoftShadow;bool m_enableAmbientOcclusion;bool m_enableHDR;bool m_enableReflection;bool m_enableRefraction;float  m_quality;bool m_sphereProject;public:PrimitiveBspTree    *m_bspPartion;LaCone3Partion      *m_eyeLaConePartion;AnguleBoxPartion    *m_eyeAnguleBoxPartion;UniformVoxelPartion *m_voxelPartion;Primitive *m_primitivesTagged[MaxPrimitive];int m_primitivesTaggedCount;RayTraceTexture* m_curTexture;FILTER m_texFilter;//预插值的跨度表 因为不是传统的投影矩阵平均插值float WRat[2048];float HRat[2048];////Primitive *m_primitivesInFrustum[MaxPrimitive];//int m_primitivesCountInFrustum;//int m_statisticPrimitivesCountInFrustumMax;//int m_statisticPrimitivesCountInFrustum[MaxPrimitive];char debugRegion;RayTracerThread*  m_traceThread;int               m_threadNum;};extern RayTraceRendDriver *G_RayTracer;

#include "Frustum.h"
#include "Camera.h"
#include "RayTraceRendDriver.h"
#include "RayTraceTexture.h"
#include "PrimitiveBspTree.h"
#include "LaCone3Partion.h"
#include "AnguleBoxPartion.h"
#include "UniformGridPartion.h"
#include <assert.h>#define  WIN32APP
#include "General/Thread.h"
#include <crtdbg.h>enum TraceThreadState
{TT_Waiting,TT_Tracing,TT_TracingCompleted,
};
class RayTracerThread: public Thread
{
public:RayTracerThread();//~RayTracerThread()//{}virtual bool Run(ThreadParm* pData);TraceThreadState m_state;int startLine;int endLine;int threadIndex;
};RayTracerThread::RayTracerThread()
:m_state(TT_Waiting)
{}bool RayTracerThread::Run(ThreadParm* pData)
{while (1){if(Thread::m_state== TS_RunningToEnd){Thread::m_state = Thread::TS_End;break;}switch(m_state){case TT_Waiting:{Sleep(1);break;}case TT_Tracing:{const int frustumSize = 16;const int halfFrustumSize = frustumSize/2;int cellY=startLine;while(cellY < endLine){int cellYEnd=cellY+frustumSize;if (cellYEnd>endLine/*-1*/){cellYEnd = endLine/*-1*/;}int cellX=0;while(cellX < G_RayTracer->m_backbufWidth){int cellXEnd=cellX+frustumSize;if (cellXEnd>G_RayTracer->m_backbufWidth-1){cellXEnd = G_RayTracer->m_backbufWidth-1;}//绘制格子G_RayTracer->RenderRect(cellX,cellY,cellXEnd,cellYEnd,threadIndex);cellX+=frustumSize;}cellY+=frustumSize;}m_state=TT_TracingCompleted;break;}default:Sleep(1);}}return true;
}Primitive::Primitive(PrimitiveType primitiveType_)
:pTexture(NULL)
,refleraTexture(NULL)
,primitiveType(primitiveType_)
,color(1,1,1)
,visible(true)
,cullface(CF_Back)
{for (int i=0;i<MaxThread;i++){tag[i]=-1;}reflection = 0;refraction = 0;Eta = 1;ODEta = 1.0f ;laYIndexMax=-1;laYIndexMin=512;laXIndexMax=-1;laXIndexMin=512;laZIndexMax=-1;laZIndexMin=512;
}void Primitive::SetColorTexture(const vec3 &color_, RayTraceTexture *texture)
{color = color_;pTexture = texture;
}void Primitive::SetRefleract(float Reflection_ /*= 0.0f*/, float Refraction_ /*= 0.0f*/, float Eta_ /*= 1.0f*/,RayTraceTexture* tex)
{reflection = Reflection_;refraction = Refraction_;Eta = Eta_;ODEta = 1.0f / Eta;refleraTexture = tex;
}TrigonPrim::TrigonPrim()
:Primitive(PT_Trigon)
,m_polygon(3)
{
}void TrigonPrim::SetPos(const vec3 &ptA_, const vec3 &ptB_, const vec3 &ptC_)
{ ptA=ptA_;ptB=ptB_;ptC=ptC_;dirAB = ptB_ - ptA_; dirBC = ptC_ - ptB_; dirCA = ptA_ - ptC_;N = (Cross(dirAB, -dirCA));N.Normalize();D = -Dot(N, ptA_);N1 = (Cross(N, dirAB));N1.Normalize();D1 = -Dot(N1, ptA_);N2 = (Cross(N, dirBC));N2.Normalize();D2 = -Dot(N2, ptB_);N3 = (Cross(N, dirCA));N3.Normalize();D3 = -Dot(N3, ptC_);lab = (dirAB.Length()); dirAB /= lab;lbc = (dirBC.Length()); dirBC /= lbc;lca = (dirCA.Length());  dirCA /= lca;//解法二  P = wa*PA + wb*PB + (1-wa-wb)*PC 方程两边同时点乘(PB叉乘PC)//得  P.Dot(PB.Cross(PC)) = wa*PA.Dot(PB.Cross(PC)) + 0 + 0;//得  wa = PA.Dot(PB.Cross(PC)) / P.Dot(PB.Cross(PC));//可以推广到四维向量插值//已知三角形的三个顶点坐标PA, PB, PC, 三角形内的任意点P。未知数u和v(wa ≥ 0, wb ≥ 0, wa + wb ≤ 1),其中wa、wb体现了PA、PB对P的权重贡献,(1 - wa - wb)是PC权重//则 P = wa*PA + wb*PB + (1-wa-wb)*PC//解方程://(P -PC) = wa*(PA-PC) + wb*(PB-PC)//可得wa、wb、wc值,对PA, PB, PC的颜色值加权平均,即得P点颜色值或坐标值。//(P.x -PC.x) = wa*(PA_PC.x) + wb*(PB_PC.x)//(P.y -PC.y) = wa*(PA_PC.y) + wb*(PB_PC.y)//(P.z -PC.z) = wa*(PA_PC.z) + wb*(PB_PC.z)//wa = [(P.x -PC.x)*(PB_PC.y)-(P.y -PC.y)*(PB_PC.x)] / [(PA_PC.x)*(PB_PC.y)-(PA_PC.y)*(PB_PC.x)]//wb = [(P.x -PC.x)*(PA_PC.y)-(P.y -PC.y)*(PA_PC.x)] / [(PB_PC.x)*(PA_PC.y)-(PB_PC.y)*(PA_PC.x)]//x y z 随意组合                                                                         //wa = [(P.x -PC.x)*(PB_PC.z)-(P.z -PC.z)*(PB_PC.x)] / [(PA_PC.x)*(PB_PC.z)-(PA_PC.z)*(PB_PC.x)]//wb = [(P.x -PC.x)*(PA_PC.z)-(P.z -PC.z)*(PA_PC.x)] / [(PB_PC.x)*(PA_PC.z)-(PB_PC.z)*(PA_PC.x)]B_C = ptB - ptC;A_C = ptA - ptC; float lineTest = B_C.x*A_C.y-B_C.y*A_C.x;if (-_EPSILON<lineTest&&lineTest<_EPSILON){//xy 平面共线(斜率相等) 计算k必须有z参与bLineXY = true;//kVal[0] == 0则kVal[1]==0,空间共线kVal[0] = A_C.x*B_C.z - A_C.z*B_C.x;kVal[1] = B_C.x*A_C.z - B_C.z*A_C.x;if (kVal[0]<-_EPSILON || _EPSILON<kVal[0]){kVal[0] = 1/kVal[0];kVal[1] = 1/kVal[1];}}else{//已经不可能空间共线bLineXY = false;kVal[0] = A_C.x*B_C.y - A_C.y*B_C.x;kVal[1] = B_C.x*A_C.y - B_C.y*A_C.x;if (kVal[0]<-_EPSILON || _EPSILON<kVal[0]){kVal[0] = 1/kVal[0];kVal[1] = 1/kVal[1];}}CalBound();
}void TrigonPrim::SetPos(const vec3 &ptA_, const vec3 &ptB_, const vec3 &ptC_,const vec3& nA_,const vec3& nB_,const vec3& nC_)
{SetPos(ptA_,ptB_,ptC_);nA = nA_;nB = nB_;nC = nC_;if (N.Dot(nA)<0){N*=-1;}
}bool TrigonPrim::Inside(float x, float y, float z)
{if(N1.x * x + N1.y * y + N1.z * z + D1 < 0.0f) return false;if(N2.x * x + N2.y * y + N2.z * z + D2 < 0.0f) return false;if(N3.x * x + N3.y * y + N3.z * z + D3 < 0.0f) return false;return true;
}bool TrigonPrim::Inside(const vec3 &point)
{if(Dot(N1, point) + D1 < 0.0f) return false;if(Dot(N2, point) + D2 < 0.0f) return false;if(Dot(N3, point) + D3 < 0.0f) return false;return true;
}bool TrigonPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes)
{//tag时过滤,提高速度//if(visible==false) return false;float NdotR = -Dot(N, rayDir);背面也可能需要被追踪到 //if(cullface==CF_None // || (cullface==CF_Back&&NdotR>0.0f) //只追踪正面//   || (cullface==CF_Front&&NdotR<0.0f)//只追踪反面//   || (refraction>0.0f)               //可以折射出的背面//)//if(NdotR>0.0f)//和面的法线逆向 只追踪正面//if(NdotR > 0.0f)  || (refraction>0.0f && NdotR<0.0f))  //追踪正面 || 可以折射出的背面 普通背面也要被折射光线追踪到{//正反面都走这里float distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < traceRes.distanceSofar){vec3 point = rayPos + rayDir * distance;bool inside = Inside(point);if (inside){traceRes.testDistance = distance;traceRes.point = point;traceRes.distanceSofar = distance;traceRes.primitive = this;}return inside;}}return false;
}
bool TrigonPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point)
{float NdotR = -Dot(N, rayDir);if(NdotR > 0.0f){distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){point = rayDir * distance + rayPos;return Inside(point);}}return false;
}bool TrigonPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance)
{float NdotR = -Dot(N, rayDir);if(NdotR > 0.0f){distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){return Inside(rayDir * distance + rayPos);}}return false;
}bool TrigonPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance)
{float NdotR = -Dot(N, rayDir);if(NdotR > 0.0f){float distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){return Inside(rayDir * distance + rayPos);}}return false;
}void TrigonPrim::CalBound()
{RitterSphere(&ptA, 3, center,radius);aabb.m_max = ptA;aabb.m_min = ptA;aabb.Merge(ptB);aabb.Merge(ptC);
}void TrigonPrim::SampleTexColor(const vec3&pos,vec3&texColor,vec3&refleraColor,FILTER filter)
{//wa = [(P.x -PC.x)*(PB_PC.y)-(P.y -PC.y)*(PB_PC.x)] / [(PA_PC.x)*(PB_PC.y)-(PA_PC.y)*(PB_PC.x)]//wb = [(P.x -PC.x)*(PA_PC.y)-(P.y -PC.y)*(PA_PC.x)] / [(PB_PC.x)*(PA_PC.y)-(PB_PC.y)*(PA_PC.x)]//x y z 随意组合                                                                      vec2 uv;if (-_EPSILON<kVal[0]&&kVal[0]<_EPSILON){uv = texA;}else{float wa,wb,wc;if (bLineXY){wa = ((pos.x-ptC.x)*B_C.z-(pos.z-ptC.z)*B_C.x)  * kVal[0];wb = ((pos.x-ptC.x)*A_C.z-(pos.z-ptC.z)*A_C.x)  * kVal[1];wc = 1-wa-wb;}else{wa = ((pos.x-ptC.x)*B_C.y-(pos.y-ptC.y)*B_C.x)  *kVal[0];wb = ((pos.x-ptC.x)*A_C.y-(pos.y-ptC.y)*A_C.x)  *kVal[1];wc = 1-wa-wb;}uv = texA*wa+texB*wb+texC*wc;}pTexture->GetColor11(uv.x, uv.y,texColor, filter);//texColor= pTexture->GetColorNearest(uv.x, uv.y);if (refleraTexture){refleraTexture->GetColor11(uv.x, uv.y,refleraColor, filter);//GetColorNearest}
}void TrigonPrim::SampleNormal(const vec3&pos,vec3& normal)
{//todo 法线贴图//normal = N;//return;if (-_EPSILON<kVal[0]&&kVal[0]<_EPSILON){normal = nA;}else{float wa,wb,wc;if (bLineXY){wa = ((pos.x-ptC.x)*B_C.z-(pos.z-ptC.z)*B_C.x)  * kVal[0];wb = ((pos.x-ptC.x)*A_C.z-(pos.z-ptC.z)*A_C.x)  * kVal[1];wc = 1-wa-wb;}else{wa = ((pos.x-ptC.x)*B_C.y-(pos.y-ptC.y)*B_C.x)  *kVal[0];wb = ((pos.x-ptC.x)*A_C.y-(pos.y-ptC.y)*A_C.x)  *kVal[1];wc = 1-wa-wb;}normal = nA*wa+nB*wb+nC*wc;}
}QuadPrim::QuadPrim()
:Primitive(PT_Quad)
,m_polygon(4)
{
}void QuadPrim::SetPos(const vec3 &ptA_, const vec3 &ptB_, const vec3 &ptC_, const vec3 &ptD_)
{ptA=ptA_;ptB=ptB_;ptC=ptC_;ptD=ptD_;B_A = ptB - ptA;D_A = ptD - ptA;m = (ptA + ptB + ptC + ptD) / 4.0f;dirAB = B_A;odDisAB = B_A.Length();if (odDisAB>_EPSILON){odDisAB = 1/odDisAB;}else{odDisAB = 9999;}odDisAC = (ptA-ptC).Length();if (odDisAC>_EPSILON){odDisAC = 1/odDisAC;}else{odDisAC = 9999;}dirAB.Normalize();N = (Cross(B_A, ptC - ptA));N.Normalize();B = Cross(N, dirAB);O = vec3(Dot(dirAB, ptA), Dot(B, ptA), Dot(N, ptA));D = -Dot(N, ptA);N1 = (Cross(N, ptB - ptA));N1.Normalize();D1 = -Dot(N1, ptA);N2 = (Cross(N, ptC - ptB));N2.Normalize();D2 = -Dot(N2, ptB);N3 = (Cross(N, ptD - ptC));N3.Normalize();D3 = -Dot(N3, ptC);N4 = (Cross(N, ptA - ptD));N4.Normalize();D4 = -Dot(N4, ptD);CalBound();
}bool QuadPrim::Inside(vec3 &point)
{if(Dot(N1, point) + D1 < 0.0f) return false;if(Dot(N2, point) + D2 < 0.0f) return false;if(Dot(N3, point) + D3 < 0.0f) return false;if(Dot(N4, point) + D4 < 0.0f) return false;return true;
}
bool QuadPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes)
{float NdotR = -Dot(N, rayDir);//和面的法线逆向if(NdotR > 0.0f) // || (refraction > 0.0f && NdotR < 0.0f)){float distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < traceRes.distanceSofar){vec3 point = rayDir * distance + rayPos;bool inside = Inside(point);if (inside){traceRes.testDistance = distance;traceRes.point = point;traceRes.distanceSofar = distance;traceRes.primitive = this;}return inside;}}return false;
}
bool QuadPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point)
{float NdotR = -Dot(N, rayDir);//和面的法线逆向if(NdotR > 0.0f) // || (refraction > 0.0f && NdotR < 0.0f)){distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){point = rayDir * distance + rayPos;return Inside(point);}}return false;
}bool QuadPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance)
{float NdotR = -Dot(N, rayDir);if(NdotR > 0.0f) // || (refraction > 0.0f && NdotR < 0.0f)){distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){return Inside(rayDir * distance + rayPos);}}return false;
}bool QuadPrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance)
{float NdotR = -Dot(N, rayDir);if(NdotR > 0.0f) // || (refraction > 0.0f && NdotR < 0.0f)){float distance = (Dot(N, rayPos) + D) / NdotR;if(distance >= 0.0f && distance < maxDistance){return Inside(rayDir * distance + rayPos);}}return false;
}void QuadPrim::CalBound()
{RitterSphere(&ptA, 4, center,radius);aabb.m_max = ptA;aabb.m_min = ptA;aabb.Merge(ptB);aabb.Merge(ptC);aabb.Merge(ptD);
}void QuadPrim::SampleTexColor(const vec3&pos,vec3&texColor,vec3&refleraColor,FILTER filter)
{?只适用aabb ,双线性插值float tx,ty,txty;float realHeight;float height[4];tx = col0f - col0i;ty = row0f - row0i;txty = tx * ty;realHeight    = height[0] * (1.0f - ty - tx + txty)+ height[1] * (tx - txty)+ height[2] * txty+ height[3] * (ty - txty);///*//D C//A B//*///float realHeight;//float height[4];//tx = (pos.x - ptD.x)/(ptC.x - ptD.x);//ty = (pos.y - ptD.y)/(ptA.y - ptD.y);//txty = tx * ty;//vec2 uv   = texA * (1.0f - ty - tx + txty)//+ texB * (tx - txty)//+ texC * txty//+ texD * (ty - txty);//return pTexture->GetColorBilinear(uv.x, uv.y);float s = (Dot(dirAB, pos) - O.x) *odDisAB;float t = (Dot(B, pos) - O.y) *odDisAC;pTexture->GetColor11(s, t,texColor, filter);if (refleraTexture){refleraTexture->GetColor11(s, t,refleraColor, filter);}
}//SpherePrim::SpherePrim()
:Primitive(PT_Sphere)
{
}void SpherePrim::SetPos(const vec3 &Position, float Radius)
{center = Position;radius = Radius;Radius2 = Radius * Radius;ODRadius = 1.0f / Radius;CalBound();
}bool SpherePrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, TraceRes& traceRes)
{vec3 L = center - rayPos;float LdotR = Dot(L, rayDir);if(LdotR > 0.0f){float D2 = L.LengthSq() - LdotR * LdotR;if(D2 < Radius2){float distance = LdotR - sqrt(Radius2 - D2);if(distance >= 0.0f && distance < traceRes.distanceSofar){traceRes.testDistance = distance;traceRes.distanceSofar = distance;traceRes.point = rayDir * distance + rayPos;traceRes.primitive = this;return true;}}}return false;
}bool SpherePrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance, vec3 &point)
{vec3 L = center - rayPos;float LdotR = Dot(L, rayDir);if(LdotR > 0.0f){float D2 = L.LengthSq() - LdotR * LdotR;if(D2 < Radius2){distance = LdotR - sqrt(Radius2 - D2);if(distance >= 0.0f && distance < maxDistance){point = rayDir * distance + rayPos;return true;}}}return false;
}bool SpherePrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance, float &distance)
{vec3 L = center - rayPos;float LdotR = Dot(L, rayDir);if(LdotR > 0.0f){float D2 = L.LengthSq() - LdotR * LdotR;if(D2 < Radius2){distance = LdotR - sqrt(Radius2 - D2);if(distance >= 0.0f && distance < maxDistance){return true;}}}return false;
}bool SpherePrim::Intersect(const vec3 &rayPos, const vec3 &rayDir, float maxDistance)
{//?没判断起点在圆内vec3 L = center - rayPos;float LdotR = Dot(L, rayDir);if(LdotR > 0.0f){float D2 = L.LengthSq() - LdotR * LdotR;if(D2 < Radius2){float distance = LdotR - sqrt(Radius2 - D2);if(distance >= 0.0f && distance < maxDistance){return true;}}}return false;
}void SpherePrim::CalBound()
{aabb.m_max = center;aabb.m_min = center;aabb.Merge(center-vec3(radius,radius,radius));aabb.Merge(center+vec3(radius,radius,radius));
}BillboardPrim::BillboardPrim()
//:Primitive(PT_Billboard)
{primitiveType = PT_Billboard;
}//LightRT::LightRT()
{Ambient = 1.0f;Diffuse = 1.0f;ConstantAttenuation = 1.0f;LinearAttenuation = 0.0f;QuadraticAttenuation = 0.0f;Sphere = NULL;Quad = NULL;m_laConePartion = new LaCone3Partion(32);//16
}LightRT::~LightRT()
{if(Sphere){delete Sphere;Sphere = NULL;}if(Quad){delete Quad;Quad = NULL;}if(m_laConePartion){delete m_laConePartion;m_laConePartion = NULL;}
}void LightRT::Update()
{m_laConePartion->Reset(Sphere ? Sphere->center : Quad->m);G_RayTracer->PartionWithLaCone(m_laConePartion);
}//TraceRes::TraceRes()
{distanceSofar = 1048576.0f;traceDepth = 0;light = NULL;primitive = NULL;
}//
RayTraceRendDriver *G_RayTracer;
RayTraceRendDriver G_RayTracer_;
CCamera G_Camera;RayTraceRendDriver::RayTraceRendDriver()
:m_presenter(NULL)
{G_RayTracer = this;m_colorBuffer = NULL;m_hdrColorBuffer = NULL;//m_colorBuffer01 = NULL;//m_hdrColorBuffer01 = NULL;//m_colorBuffer02 = NULL;//m_hdrColorBuffer02 = NULL;//反射两次已经足够,反射一次都可以MaxTraceDepth = 2;FarPlainDis = 1000;SamplesPerPixel = 1;GISampleNum = 4;//16ODGISamples = 1.0f / (float)GISampleNum;AmbientOcclusionIntensity = 0.5f;ODGISamplesXAmbientOcclusionIntensity = ODGISamples * AmbientOcclusionIntensity;m_lights = NULL;m_lightsCount = 0;m_primitivesVolume = MaxPrimitive;m_primitivesCount = 0;m_primitives = new Primitive *[m_primitivesVolume];m_enableTexture2D = true;m_enableShadow = true;m_enableSoftShadow = false;m_enableAmbientOcclusion = false;m_enableHDR = false;m_enableReflection = true;m_enableRefraction = true;m_quality = 1;m_sphereProject = false;m_bspPartion = new PrimitiveBspTree;m_voxelPartion = new UniformVoxelPartion;m_eyeLaConePartion = new LaCone3Partion(32);//16m_eyeAnguleBoxPartion = new AnguleBoxPartion(16);m_lights = new LightRT[8];m_curTexture = NULL;m_texFilter = Bilinear;
}RayTraceRendDriver::~RayTraceRendDriver()
{Close();
}bool RayTraceRendDriver::Init()
{_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ );assert(_CrtCheckMemory());//_CrtSetBreakAlloc(18835); m_threadNum = 4;m_traceThread = new RayTracerThread[m_threadNum];for (int i=0;i<m_threadNum;i++){m_traceThread[i].threadIndex = i;m_traceThread[i].startLine = i*m_backbufHeight/m_threadNum;  //400/2m_traceThread[i].endLine = (i+1)*m_backbufHeight/m_threadNum;m_traceThread[i].Start();}return true;
}void RayTraceRendDriver::Close()
{if (m_traceThread){for (int i=0;i<m_threadNum;i++){m_traceThread[i].Stop();}delete[] m_traceThread;m_traceThread = NULL;}//for//if (m_primitives){//for (int i=0;i<m_primitivesCount;i++)//{//    Primitive* primi = m_primitives[i];//创建的是数组 此处会crash// delete primi;//}delete[] m_primitives;m_primitives = NULL;}if(m_lights != NULL){delete [] m_lights;m_lights = NULL;}if (m_bspPartion){delete m_bspPartion;m_bspPartion = NULL;}if (m_voxelPartion){delete m_voxelPartion;m_voxelPartion = NULL;}if(m_eyeLaConePartion){delete m_eyeLaConePartion;m_eyeLaConePartion = NULL;}if(m_eyeAnguleBoxPartion){delete m_eyeAnguleBoxPartion;m_eyeAnguleBoxPartion = NULL;}if(m_colorBuffer != NULL){delete [] m_colorBuffer;m_colorBuffer = NULL;}if(m_hdrColorBuffer != NULL){delete [] m_hdrColorBuffer;m_hdrColorBuffer = NULL;}//if(m_colorBuffer01 != NULL)//{//    delete [] m_colorBuffer01;//    m_colorBuffer01 = NULL;//}//if(m_hdrColorBuffer01 != NULL)//{//   delete [] m_hdrColorBuffer01;// m_hdrColorBuffer01 = NULL;//}//if(m_colorBuffer02 != NULL)//{//   delete [] m_colorBuffer02;//    m_colorBuffer02 = NULL;//}//if(m_hdrColorBuffer02 != NULL)//{//   delete [] m_hdrColorBuffer02;// m_hdrColorBuffer02 = NULL;//}
}void RayTraceRendDriver::OnSize(int width, int height)
{m_wndWidth = width;m_wndHeight = height;m_backbufWidth = width/m_quality;m_backbufHeight = height/m_quality;if(m_colorBuffer != NULL){delete [] m_colorBuffer;m_colorBuffer = NULL;}if(m_hdrColorBuffer != NULL){delete [] m_hdrColorBuffer;m_hdrColorBuffer = NULL;}if(m_backbufWidth > 0 && m_backbufHeight > 0){int WidthMod4 = m_backbufWidth%4;if(WidthMod4 > 0){m_backbufWidth += 4 - WidthMod4;}m_colorBuffer = new BYTE[m_backbufWidth * m_backbufHeight * 3];m_hdrColorBuffer = new vec3[m_backbufWidth * m_backbufHeight];WidthMSamples = m_backbufWidth * SamplesPerPixel;HeightMSamples = m_backbufHeight * SamplesPerPixel;WidthXHeightXSamplesSq = WidthMSamples * HeightMSamples;ODSamplesSq = 1.0f / (float)(SamplesPerPixel * SamplesPerPixel);ODSamples = 1.0f / (float)(SamplesPerPixel);//采样实数像素平均出整数像素反锯齿   第一个矩阵将像素归一G_Camera.matPixelNormal[0] = 1.0f / (float)(WidthMSamples - 1);G_Camera.matPixelNormal[5] = 1.0f / (float)(HeightMSamples - 1);float aspect = ((float)m_backbufWidth) /m_backbufHeight;G_Camera.SetAspect(aspect);CalRat();//?? waitfor (int i=0;i<m_threadNum;i++){m_traceThread[i].startLine = i*m_backbufHeight/m_threadNum;  //400/2m_traceThread[i].endLine = (i+1)*m_backbufHeight/m_threadNum;}}
}void RayTraceRendDriver::SetPresenter(Presenter* presenter)
{m_presenter = presenter;
}void RayTraceRendDriver::ClearColorBuffer()
{if(m_colorBuffer != NULL){memset(m_colorBuffer, 0, m_backbufWidth * m_backbufHeight * 3);}
}void RayTraceRendDriver::Render()
{if(m_colorBuffer == NULL) return;vec3 eyePos = G_Camera.m_eyePos;m_eyeLaConePartion->Reset(G_Camera.m_eyePos);PartionWithLaCone(m_eyeLaConePartion);//m_eyeAnguleBoxPartion->Reset(G_Camera.m_eyePos);//PartionWithAnguleBox(m_eyeAnguleBoxPartion);for (int i=0;i<m_threadNum;i++){m_traceThread[i].m_state = TT_Tracing;}while (1){bool completed = true;for (int i=0;i<m_threadNum;i++){if(m_traceThread[i].m_state != TT_TracingCompleted){completed = false;break;}}if (completed==true){break;}Sleep(1);}//const int frustumSize = 16;//const int halfFrustumSize = frustumSize/2;//int cellY=0;//while(cellY < m_backbufHeight)//{//   int cellYEnd=cellY+frustumSize;// if (cellYEnd>m_backbufHeight)//  {//     cellYEnd = m_backbufHeight;//  }// int cellX=0;// while(cellX < m_backbufWidth)//  {//     int cellXEnd=cellX+frustumSize;//     if (cellXEnd>m_backbufWidth)//       {//         cellXEnd = m_backbufWidth;//       }//     //绘制格子//        RenderRect(cellX,cellY,cellXEnd,cellYEnd,0);//      cellX+=frustumSize;// }// cellY+=frustumSize;//}//if(m_enableHDR)AfterEffectHDR();
}void RayTraceRendDriver::RenderRect(int cellX,int cellY,int cellXEnd,int cellYEnd,int threadIndex)
{vec3 eyePos = G_Camera.m_eyePos;//第一次投射 使用二叉视椎标记图元的flag //第二次投射 视锥点为第一次视锥点(eye)相对于平面的对称点  椎体角度不变长度被拉长 剔除效率变低//第三次投射 视锥点为前一次视锥点相对于平面对称点 同上。。。//???第二次投射因为第一次交面不只有一个,所以反射椎会有多个,已经不适用该算法了,另外球形图元反射视锥不好计算或太大int line=cellY;vec3 rayDir;vec3 color;while(line < cellYEnd){BYTE *colorbuffer = m_colorBuffer + (m_backbufWidth * line+cellX) * 3 ;vec3 *hdrcolorbuffer = m_hdrColorBuffer + (m_backbufWidth * line+cellX);/*D CA B*/float rat = 1-HRat[line];//((float)line)*odHeight_1;vec3 dirLineStart = G_Camera.ptDw*(1-rat)+ G_Camera.ptAw*(rat);vec3 dirLineEnd = G_Camera.ptCw*(1-rat)+ G_Camera.ptBw*(rat);for(int x = cellX; x < cellXEnd; x++){//if (x<cellX+halfFrustumSize)//{//  if (line<cellY+halfFrustumSize)//   {//     debugRegion = 1;// }// else//  {//     debugRegion = 2;// }//}//else{debugRegion = -1;}//ui不带alpha覆盖的地方不要追踪if(colorbuffer[0]==0 && colorbuffer[1]==0 && colorbuffer[2]==0) {if (SamplesPerPixel==1){//rayDir = (G_Camera.RayMatrix * vec3(x,line, 0.0f));//用插值代替上面的矩阵乘法 带旋转的世界坐标系 不能简单插值xyrat = WRat[x];//((float)x)*odWidth_1;rayDir  = dirLineStart*(1-rat)+ dirLineEnd*(rat);rayDir.Normalize();//这里不能返回alpha和backbuff混合,因为backbuff未被追踪,透明贴图需要继续追踪color = TraceRay(eyePos, rayDir,0,0,threadIndex);*hdrcolorbuffer = color;colorbuffer[2] = color.r <= 0.0f ? 0 : color.r >= 1.0 ? 255 : (BYTE)(color.r * 255);colorbuffer[1] = color.g <= 0.0f ? 0 : color.g >= 1.0 ? 255 : (BYTE)(color.g * 255);colorbuffer[0] = color.b <= 0.0f ? 0 : color.b >= 1.0 ? 255 : (BYTE)(color.b * 255);}else{//浮点像素追踪后取均值vec3 SamplesSum;//todo lerp y//for(int sy = 0; sy < SamplesPerPixel; sy++){for(int sx = 0; sx < SamplesPerPixel; sx++){//rayDir = G_Camera.RayMatrix * vec3((float)(X + sx), (float)Yyy, 0.0f);//todo lerp yrat = Lerp(WRat[x],WRat[x+1],sx*ODSamples);//((float)x)*odWidth_1;rayDir  = dirLineStart*(1-rat)+ dirLineEnd*(rat);rayDir.Normalize();color = TraceRay(G_Camera.m_eyePos, rayDir, 0, NULL, threadIndex);SamplesSum.r += color.r <= 0.0f ? 0.0f : color.r >= 1.0 ? 1.0f : color.r;SamplesSum.g += color.g <= 0.0f ? 0.0f : color.g >= 1.0 ? 1.0f : color.g;SamplesSum.b += color.b <= 0.0f ? 0.0f : color.b >= 1.0 ? 1.0f : color.b;}}SamplesSum.r *= ODSamples;SamplesSum.g *= ODSamples;SamplesSum.b *= ODSamples;//SamplesSum.r *= ODSamplesSq;//SamplesSum.g *= ODSamplesSq;//SamplesSum.b *= ODSamplesSq;*hdrcolorbuffer = SamplesSum;colorbuffer[2] = (BYTE)(SamplesSum.r * 255);colorbuffer[1] = (BYTE)(SamplesSum.g * 255);colorbuffer[0] = (BYTE)(SamplesSum.b * 255);}}hdrcolorbuffer++;colorbuffer += 3;}line++;}
}void RayTraceRendDriver::CalRat()
{float aspect = ((float)m_backbufWidth) /m_backbufHeight;//像素对应的射线方向权重预插值的跨度表//球形视口  方法一二 都是默认线性像素 视口边缘可能拉伸(?鱼眼收缩),使用环形视口改进   ?传统管线也存在此问题//每个像素使用一次tan直接计算出射线方向 替代方法一二中的前三个矩阵float odHeight_1 = 1.0f/(m_backbufHeight-1);float odWidth_1 = 1.0f/(m_backbufWidth-1);//传统的投影矩阵平均插值if (m_sphereProject==false){for (int w=0;w<m_backbufWidth;w++){WRat[w] = w*odWidth_1;}for (int h=0;h<m_backbufHeight;h++){HRat[h] = h*odHeight_1;}}else{//自变量圆割上的x,tan(x), ang的导数float tanfov2 = tan(G_Camera.m_fov/2);//0 width 对应-+fov/2float startAng = -G_Camera.m_fov/2;for (int w=0;w<m_backbufWidth;w++){float x = w*odWidth_1;//0~1x = x*2 -1; //-1~1x*=tanfov2;//x*=aspect;float ang = atan(x);WRat[w] = (ang-startAng)/G_Camera.m_fov;//当前像素对应角度的占比}for (int h=0;h<m_backbufHeight;h++){float y = h*odHeight_1;//0~1y = y*2 -1; //-1~1y*=tanfov2;float ang = atan(y);HRat[h] = (ang-startAng)/G_Camera.m_fov;//当前像素对应角度的占比}}
}int  RayTraceRendDriver::GetSamples()
{return SamplesPerPixel;
}void RayTraceRendDriver::AfterEffectHDR()
{if(m_colorBuffer == NULL || m_hdrColorBuffer == NULL) return;float SumLum = 0.0f;//最亮的float LumWhite = 0.0f;int LumNotNull = 0;vec3 *hdrColor = m_hdrColorBuffer;float Luminance;for(int i = 0; i < WidthXHeightXSamplesSq; i++){//Luminance = (hdrColor->r * 0.2125f + hdrColor->g * 0.7154f + hdrColor->b * 0.0721f);Luminance = (hdrColor->r * 0.30f + hdrColor->g * 0.59f + hdrColor->b * 0.11f);if(Luminance > 0.0f){SumLum += Luminance;LumNotNull++;LumWhite = LumWhite > Luminance ? LumWhite : Luminance;}hdrColor++;}float AvgLum = SumLum / (float)LumNotNull;float odAvgLum;if (AvgLum>0.00001){odAvgLum = 1/AvgLum;}else{odAvgLum = 0;}LumWhite /= AvgLum;float LumWhiteSq = LumWhite * LumWhite;hdrColor = m_hdrColorBuffer;vec3 newColor;float LumRel;float MappingFactor;for(int i = 0; i < WidthXHeightXSamplesSq; i++){//Luminance = (hdrColor->r * 0.2125f + hdrColor->g * 0.7154f + hdrColor->b * 0.0721f);Luminance = (hdrColor->r * 0.30f + hdrColor->g * 0.59f + hdrColor->b * 0.11f);LumRel = Luminance * odAvgLum;//MappingFactor = LumRel * (1.0f + LumRel / LumWhiteSq) / (1.0f + LumRel);//MappingFactor = sqrt(sqrt(LumRel));MappingFactor = sqrt(LumRel);//MappingFactor = (LumRel);newColor.r = hdrColor->r * MappingFactor;newColor.g = hdrColor->g * MappingFactor;newColor.b = hdrColor->b * MappingFactor;hdrColor->r = newColor.r <= 0.0f ? 0.0f : newColor.r >= 1.0f ? 1.0f : newColor.r;hdrColor->g = newColor.g <= 0.0f ? 0.0f : newColor.g >= 1.0f ? 1.0f : newColor.g;hdrColor->b = newColor.b <= 0.0f ? 0.0f : newColor.b >= 1.0f ? 1.0f : newColor.b;hdrColor++;}//int LineWidth_WidthX3 = (m_backbufWidth - m_backbufWidth) * 3;BYTE *colorbuffer = m_colorBuffer;hdrColor = m_hdrColorBuffer;for(int y = 0; y < m_backbufHeight; y++){for(int x = 0; x < m_backbufWidth; x++){colorbuffer[2] = (BYTE)(hdrColor->r * 255);colorbuffer[1] = (BYTE)(hdrColor->g * 255);colorbuffer[0] = (BYTE)(hdrColor->b * 255);hdrColor++;colorbuffer += 3;}colorbuffer += LineWidth_WidthX3;}
}bool RayTraceRendDriver::SetSamples(int Samples)
{if(SamplesPerPixel == Samples)return false;SamplesPerPixel = Samples;OnSize(m_backbufWidth, m_backbufHeight);return true;
}void RayTraceRendDriver::Present()
{if(m_presenter)m_presenter->Present(m_backbufWidth,m_backbufHeight,m_colorBuffer);//调试 保存为图片//IFileManager m;//bool yes=m.ExportFile_PPM("savedebug.ppm", mBufferWidth, mBufferHeight, *m_pOutColorBuffer,true);
}bool RayTraceRendDriver::TraceShadow(const Primitive *except, const vec3 &lightPos, const vec3 &lightDir, float lightDis,int threadindex)
{LaConeCross* laCross = m_lights[0].m_laConePartion->GetLaConeCross(lightDir);Primitive **EndPrimitive = laCross->m_primitives + laCross->m_primitivesCount;Primitive *primitive;for(Primitive **pprimitive = laCross->m_primitives; pprimitive < EndPrimitive; pprimitive++){primitive = *pprimitive;if(primitive == except) continue;实测虚函数稍慢0.94s//if (primitive->Intersect(point, lightDir, lightDis))//{//   return true;//}实测: switch0.88s , if else0.91sswitch(primitive->primitiveType){case PT_Sphere: {SpherePrim *Sphere = (SpherePrim *)primitive;if (Sphere->Intersect(lightPos, lightDir, lightDis)){//todo 更精确的不可以直接返回,还要看遮挡点的alpha值或折射度//速度?  alpha值0.5是半遮挡; 0是不遮挡直接在相交测试中alpha测试剔除?return true;}}break;case PT_Billboard:{float distance;vec3 respos;SpherePrim *sphere = (SpherePrim *)primitive;//vec3 lightPos = lightPos+lightDir*lightDis;//todoif (sphere->Intersect(lightPos, lightDir, lightDis,distance,respos)){//todo 更精确的不可以直接返回,还要看遮挡点的alpha值或折射度//考虑到速度,暂时只对公告板物体判断透明度//纹理if(m_enableTexture2D && sphere->refleraTexture){//和sphere唯一区别是纹理坐标的计算//将碰撞点转换到以射线为-z,以球心为原点的正交坐标系,只要根据xy插值坐标即可mat4 mat;mat.LookAt(lightPos,sphere->center,G_Camera.m_localY/*vec3(0,1,0)*/);vec3 newpos = mat*(respos);float s = newpos.x/sphere->radius*0.5f+0.5f;float t = newpos.y/sphere->radius*0.5f+0.5f;//if (sphere->refleraTexture){vec3 tempcolor;sphere->refleraTexture->GetColor11(s, t,tempcolor,m_texFilter);float refract = tempcolor.g;if (refract<0.5f){return true;}}}else{return true;}}}break;case PT_Quad:{      QuadPrim *Quad = (QuadPrim *)primitive;if (Quad->Intersect(lightPos, lightDir, lightDis)){return true;}}break;case PT_Trigon:{      TrigonPrim *trigon = (TrigonPrim *)primitive;if (trigon->Intersect(lightPos, lightDir, lightDis)){return true;}}break;}}return false;稍慢//float TestDistance;体素遍历即时返回//if(m_voxelPartion->Intersect(lightPos, lightDir,lightDis, TestDistance,except))//  return true;return false;}vec3 RayTraceRendDriver::LightIntensity(const Primitive *except, const vec3 &point, const vec3 &normal, const vec3 &lightPos, LightRT *light, float AO,int threadindex)
{vec3 lightDir = point - lightPos;float LightDis2 = lightDir.LengthSq();float lightDis = sqrt(LightDis2);lightDir *= 1.0f / lightDis;float Attenuation = light->QuadraticAttenuation * LightDis2 + light->LinearAttenuation * lightDis + light->ConstantAttenuation;float NdotLD = -Dot(normal, lightDir);//if(NdotLD > 0.0f){if(light->Sphere){if(m_enableShadow==false||TraceShadow(except, lightPos, lightDir, lightDis, threadindex) == false){//环境光+漫反射return light->Sphere->color * ((light->Ambient * AO + light->Diffuse * NdotLD) / Attenuation);}}else{float LNdotLD = Dot(light->Quad->N, lightDir);if(LNdotLD > 0.0f){if(m_enableShadow==false||TraceShadow(except, lightPos, lightDir, lightDis, threadindex) == false){//环境光+漫反射return light->Quad->color * ((light->Ambient * AO + light->Diffuse * NdotLD * LNdotLD) / Attenuation);}}}}//物体内的背面?//阴影 只有环境光return (light->Sphere ? light->Sphere->color : light->Quad->color) * (light->Ambient * AO / Attenuation);
}float ODRM = 1.0f / (float)RAND_MAX;
float TDRM = 2.0f / (float)RAND_MAX;float RayTraceRendDriver::AmbientOcclusionFactor(const Primitive *except, const vec3 &point, const vec3 &normal,int threadindex)
{//环境光遮蔽 16次随机方向采样float AO = 0.0f;for(int i = 0; i < GISampleNum; i++){//不能随机会闪烁? 固定若干方向,每帧计算一部分(静态可以 动态不行)?vec3 RandomRay = (vec3(TDRM * (float)rand() - 1.0f, TDRM * (float)rand() - 1.0f, TDRM * (float)rand() - 1.0f));RandomRay.Normalize();float NdotRR = Dot(normal, RandomRay);if(NdotRR < 0.0f){RandomRay = -RandomRay;NdotRR = -NdotRR;}float distance = 1048576.0f;float TestDistance;//TagWithVoxel(point, RandomRay);//Primitive **EndPrimitive = m_primitivesTagged + m_primitivesTaggedCount;//Primitive *primitive;//for(Primitive **pprimitive = m_primitivesTagged; pprimitive < EndPrimitive; pprimitive++)//{//   primitive = *pprimitive;// if(primitive == except) continue;//   switch(primitive->primitiveType)//   {// case PT_Sphere: case PT_Billboard://        {//         SpherePrim *Sphere = (SpherePrim *)primitive;//            if (Sphere->Intersect(point, RandomRay, distance, TestDistance))//           {//             distance = TestDistance;//         }//     }//     break;//    case PT_Quad://     {       //          QuadPrim *Quad = (QuadPrim *)primitive;//          if (Quad->Intersect(point, RandomRay, distance, TestDistance))//         {//             distance = TestDistance;//         }//     }//     break;//    case PT_Trigon://       {       //          TrigonPrim *trigon = (TrigonPrim *)primitive;//            if (trigon->Intersect(point, RandomRay, distance, TestDistance))//           {//             distance = TestDistance;//         }//     }//     break;//    }//}//体素遍历即时返回if(m_voxelPartion->Intersect(point, RandomRay,distance, TestDistance,except,threadindex))distance = TestDistance;AO += NdotRR / (1.0f + distance * distance);}return 1.0f - AO * ODGISamplesXAmbientOcclusionIntensity;
}void RayTraceRendDriver::IlluminatePoint(const Primitive *except, const vec3 &point, const vec3 &normal, vec3 &color,int threadindex)
{float AO = 1.0f;if(m_enableAmbientOcclusion){AO = AmbientOcclusionFactor(except, point, normal,threadindex);}if(m_lightsCount == 0){vec3 cam =G_Camera.m_eyePos - point;cam.Normalize();float NdotCD = Dot(normal, cam);if(NdotCD > 0.0f){color *= 0.5f * (AO + NdotCD);}else{color *= 0.5f * AO;}}else if(m_enableSoftShadow == false||m_enableShadow == false){vec3 LightsIntensitiesSum;LightRT *EndLight = m_lights + m_lightsCount;for(LightRT *light = m_lights; light < EndLight; light++){LightsIntensitiesSum += LightIntensity(except, point, normal, light->Sphere ? light->Sphere->center : light->Quad->m, light, AO, threadindex);}color *= LightsIntensitiesSum;}else{vec3 LightsIntensitiesSum;LightRT *EndLight = m_lights + m_lightsCount;for(LightRT *light = m_lights; light < EndLight; light++){if(light->Sphere){//todo 模拟辐射度 16次随机方向采样//体积光源产生边缘模糊的阴影 =》阴影闪烁for(int i = 0; i < GISampleNum; i++){vec3 RandomRay = vec3(TDRM * (float)rand() - 1.0f, TDRM * (float)rand() - 1.0f, TDRM * (float)rand() - 1.0f);RandomRay.Normalize();vec3 RandomLightPos = RandomRay * light->Sphere->radius + light->Sphere->center;LightsIntensitiesSum += LightIntensity(except, point, normal, RandomLightPos, light, AO, threadindex);}}else{for(int i = 0; i < GISampleNum; i++){float s = ODRM * (float)rand();float t = ODRM * (float)rand();vec3 RandomLightPos = light->Quad->B_A * s + light->Quad->D_A * t + light->Quad->ptA;LightsIntensitiesSum += LightIntensity(except, point, normal, RandomLightPos, light, AO, threadindex);}}}color *= LightsIntensitiesSum * ODGISamples;}
}float M_1_PI_2 = (float)M_1_PI * 0.5f;vec3 RayTraceRendDriver::TraceRay(const vec3 &rayPos, const vec3 &rayDir, int depth, Primitive *except,int threadindex)
{TraceRes traceRes;traceRes.traceDepth = depth;traceRes.rayPos = rayPos;traceRes.rayDir = rayDir;//第一次if (depth==0){//深度0有缓存,一射线剔除碰撞LaConeCross* anxel = m_eyeLaConePartion->GetLaConeCross(rayDir);Primitive **EndPrimitive = anxel->m_primitives + anxel->m_primitivesCount;Primitive *primitive;for(Primitive **pprimitive = anxel->m_primitives; pprimitive < EndPrimitive; pprimitive++){primitive = *pprimitive;if(primitive == except) continue;switch(primitive->primitiveType){case PT_Sphere: case PT_Billboard:{SpherePrim *Sphere = (SpherePrim *)primitive;Sphere->Intersect(rayPos, rayDir, traceRes);}break;case PT_Quad:{        QuadPrim *Quad = (QuadPrim *)primitive;Quad->Intersect(rayPos, rayDir, traceRes);}break;case PT_Trigon:{        TrigonPrim *trigon = (TrigonPrim *)primitive;trigon->Intersect(rayPos, rayDir, traceRes);}break;}}/*Boxel* boxel = m_eyeAnguleBoxPartion->GetBoxel(rayDir);Primitive **EndPrimitive = boxel->m_primitives + boxel->m_primitivesCount;Primitive *primitive;for(Primitive **pprimitive = boxel->m_primitives; pprimitive < EndPrimitive; pprimitive++){primitive = *pprimitive;if(primitive == except) continue;switch(primitive->primitiveType){case PT_Sphere: case PT_Billboard:{SpherePrim *Sphere = (SpherePrim *)primitive;Sphere->Intersect(rayPos, rayDir, traceRes);}break;case PT_Quad:{     QuadPrim *Quad = (QuadPrim *)primitive;Quad->Intersect(rayPos, rayDir, traceRes);}break;case PT_Trigon:{        TrigonPrim *trigon = (TrigonPrim *)primitive;trigon->Intersect(rayPos, rayDir, traceRes);}break;}}*/体素遍历即时返回//m_voxelPartion->Intersect(rayPos, rayDir,traceRes,NULL);//测试if (debugRegion==1){traceRes.primitive = NULL;int primCount = anxel->m_primitivesCount;traceRes.color.r = primCount/255.0f;traceRes.color.g = (primCount-255)/255.0f;traceRes.color.b = (primCount-510)/255.0f;}}else{第二级深度开始不方便缓存 即时剔除//体素遍历即时返回m_voxelPartion->Intersect(rayPos, rayDir,traceRes,except,threadindex);测试//if (debugShader==2)//{// traceRes.primitive = NULL;//   int primCount = laCross->m_primitivesCount;//   traceRes.color.r = primCount/255.0f;// traceRes.color.g = (primCount-255)/255.0f;//   traceRes.color.b = (primCount-510)/255.0f;//}第二级深度开始不方便缓存 即时剔除稍慢//TagWithBsp(rayPos,rayDir);//Primitive **EndPrimitive = m_primitivesTagged + m_primitivesTaggedCount;//Primitive *primitive;//for(Primitive **pprimitive = m_primitivesTagged; pprimitive < EndPrimitive; pprimitive++)//{//  primitive = *pprimitive;// if(primitive == except) continue;//   //primitive->Intersect(rayPos, rayDir, traceRes);//  switch(primitive->primitiveType)//   {// case PT_Sphere: case PT_Billboard://        {//         SpherePrim *Sphere = (SpherePrim *)primitive;//            Sphere->Intersect(rayPos, rayDir, traceRes);//       }//     break;//    case PT_Quad://     {       //          QuadPrim *Quad = (QuadPrim *)primitive;//          Quad->Intersect(rayPos, rayDir, traceRes);//     }//     break;//    case PT_Trigon://       {       //          TrigonPrim *trigon = (TrigonPrim *)primitive;//            trigon->Intersect(rayPos, rayDir, traceRes);//       }//     break;//    }//}}LightRT *EndLight = m_lights + m_lightsCount;for(LightRT *light = m_lights; light < EndLight; light++){if(light->Sphere){if(light->Sphere->Intersect(rayPos, rayDir, traceRes.distanceSofar, traceRes.testDistance, traceRes.testPoint)){traceRes.point = traceRes.testPoint;traceRes.distanceSofar = traceRes.testDistance;traceRes.light = light;traceRes.primitive = NULL;}}else{if(light->Quad->Intersect(rayPos, rayDir, traceRes.distanceSofar, traceRes.testDistance, traceRes.testPoint)){traceRes.point = traceRes.testPoint;traceRes.distanceSofar = traceRes.testDistance;traceRes.light = light;traceRes.primitive = NULL;}}}if(traceRes.light){traceRes.color = traceRes.light->Sphere ? traceRes.light->Sphere->color : traceRes.light->Quad->color;}else if(traceRes.primitive){vec3 texColor;vec3 refleraColor;vec3 ptNormal;switch(traceRes.primitive->primitiveType){case PT_Sphere: {SpherePrim* sphere = (SpherePrim*)(traceRes.primitive);traceRes.color = sphere->color;//*sphere->ODRadius =>normlized vec3 normal = (traceRes.point - sphere->center) * sphere->ODRadius;//纹理if(m_enableTexture2D && sphere->pTexture){float s = atan2(normal.x, normal.z) * M_1_PI_2 + 0.5f;float t = asin(normal.y < -1.0f ? -1.0f : normal.y > 1.0f ? 1.0f : normal.y) * (float)M_1_PI + 0.5f;vec3 tempcolor;sphere->pTexture->GetColor11(s, t,tempcolor,m_texFilter);traceRes.color *= tempcolor;//traceRes.color *= sphere->SampleTexColor( traceRes.point,m_texFilter);if (sphere->refleraTexture){sphere->refleraTexture->GetColor11(s, t,refleraColor,m_texFilter);}}//光照IlluminatePoint(sphere, traceRes.point, normal, traceRes.color, threadindex);//todo lerp(color,fle,fra,rat1,rat2,rat3)if (depth<MaxTraceDepth){float reflection = sphere->reflection;float refraction = sphere->refraction;//float Eta = trigon->Eta;//float ODEta = trigon->ODEta;//从折射贴图取得折射系数if (sphere->refleraTexture){reflection = refleraColor.r;refraction = refleraColor.g;//Eta = refleraColor.b;//if(Eta>_EPSILON)ODEta = 1/Eta; else ODEta = 99999;}//反射if(m_enableReflection && reflection > 0.0f){vec3 ReflectedRay = Reflect(rayDir, normal);traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, ReflectedRay, depth+1, sphere,threadindex), reflection);}//纹理alpha穿透,这里不能返回alpha和backbuff混合,因为backbuff未被追踪,//透明贴图需要继续追踪  根据纹理alpha调整折射系数和折射率//追踪深度不能受到半透限制,否则草丛只追有限的几层,效率?//折射     if(m_enableRefraction && refraction > 0.0f){vec3 RefractedRay = Refract(rayDir, normal, sphere->ODEta);vec3 L = sphere->center - traceRes.point;float LdotRR = Dot(L, RefractedRay);float D2 = L.LengthSq() - LdotRR * LdotRR;//assert(dis>=0);float dis_ = sphere->Radius2 - D2;if (dis_<0){dis_ = 0;}float distance = LdotRR + sqrt(dis_);//distance = LdotRR *2;  //?vec3 NewPoint = traceRes.point + RefractedRay*distance;vec3 NewNormal = (sphere->center - NewPoint) * sphere->ODRadius;//todo 球内穿越的距离 会积累球的颜色 类似体积雾RefractedRay = Refract(RefractedRay, NewNormal, sphere->Eta);//todo 重新采样射出点折射系数traceRes.color = Lerp(traceRes.color, TraceRay(NewPoint, RefractedRay, depth+1, sphere,threadindex), refraction);}}}break;case PT_Billboard:{BillboardPrim* sphere = (BillboardPrim*)(traceRes.primitive);traceRes.color = sphere->color;//*sphere->ODRadius =>normlized vec3 normal = (traceRes.point - sphere->center) * sphere->ODRadius;//纹理if(m_enableTexture2D && sphere->pTexture){//和sphere唯一区别是纹理坐标的计算//将碰撞点转换到以射线为-z,以球心为原点的正交坐标系,只要根据xy插值坐标即可mat4 mat;mat.LookAt(rayPos,sphere->center,G_Camera.m_localY/*vec3(0,1,0)*/);vec3 newpos = mat*(traceRes.point);//-sphere->center);//vec3 newDir(sphere->center-rayPos);//newDir.Normalize();//mat.FromToDir(newDir/*rayDir*/,vec3(0,0,-1));//vec3 newDir(0,rayDir.y,-1);//newDir.Normalize();//mat.FromToDir(rayDir,newDir);//mat.FromRotateY(atan2(rayDir.x,rayDir.z));//vec3 newpos = mat*(traceRes.point-sphere->center);float s = newpos.x/sphere->radius*0.5f+0.5f;float t = newpos.y/sphere->radius*0.5f+0.5f;vec3 tempcolor;sphere->pTexture->GetColor11(s, t,tempcolor,m_texFilter);traceRes.color *= tempcolor;//traceRes.color *= sphere->SampleTexColor( traceRes.point,m_texFilter);if (sphere->refleraTexture){sphere->refleraTexture->GetColor11(s, t,refleraColor,m_texFilter);//GetColorBilinear}}//插值法线 todo 法线贴图//sphere->SampleNormal(traceRes.point,ptNormal);//光照  todo透明不参与光照IlluminatePoint(sphere, traceRes.point, normal, traceRes.color, threadindex);//todo lerp(color,fle,fra,rat1,rat2,rat3)if (depth<MaxTraceDepth){float reflection = sphere->reflection;float refraction = sphere->refraction;//float Eta = trigon->Eta;//float ODEta = trigon->ODEta;//从折射贴图取得折射系数if (sphere->refleraTexture){reflection = refleraColor.r;refraction = refleraColor.g;//Eta = refleraColor.b;//if(Eta>_EPSILON)ODEta = 1/Eta; else ODEta = 99999;}//反射if(m_enableReflection && reflection > 0.0f){vec3 ReflectedRay = Reflect(rayDir, normal);traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, ReflectedRay, depth+1, sphere,threadindex), reflection);}//纹理alpha穿透,这里不能返回alpha和backbuff混合,因为backbuff未被追踪,//透明贴图需要继续追踪  根据纹理alpha调整折射系数和折射率//追踪深度不能受到半透限制,否则草丛只追有限的几层,效率?//折射  alphaif(m_enableRefraction && refraction > 0.0f){//仅仅是透明效果traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, rayDir, depth+1, sphere,threadindex), refraction);//traceRes.color = TraceRay(traceRes.point, rayDir, depth+1, sphere);}}}break;case PT_Quad:{QuadPrim* quad = (QuadPrim*)(traceRes.primitive);traceRes.color = quad->color;//纹理if(m_enableTexture2D && quad->pTexture){quad->SampleTexColor( traceRes.point,texColor,refleraColor,m_texFilter);traceRes.color *= texColor;}插值法线//quad->SampleNormal(traceRes.point,ptNormal);ptNormal = quad->N;//光照IlluminatePoint(quad, traceRes.point, ptNormal, traceRes.color, threadindex);if (depth<MaxTraceDepth){float reflection = quad->reflection;float refraction = quad->refraction;//float Eta = trigon->Eta;//float ODEta = trigon->ODEta;//从折射贴图取得折射系数if (quad->refleraTexture){reflection = refleraColor.r;refraction = refleraColor.g;//Eta = refleraColor.b;//if(Eta>_EPSILON)ODEta = 1/Eta; else ODEta = 99999;}//反射if(m_enableReflection && reflection > 0.0f){vec3 ReflectedRay = Reflect(rayDir, ptNormal);traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, ReflectedRay, depth+1, quad,threadindex), reflection);}//todo 球内穿越的距离 会积累球的颜色 类似体积雾//todo 反面要能碰撞检测到//折射 alphaif(m_enableRefraction && refraction > 0.0f){float Angle = -Dot(ptNormal, rayDir);vec3 normal;float Eta;if(Angle > 0.0f){normal = ptNormal;Eta = quad->ODEta;}else{normal = -ptNormal;Eta = quad->Eta;}vec3 RefractedRay = Refract(rayDir, normal, Eta);if(RefractedRay.x == 0.0f && RefractedRay.y == 0.0f && RefractedRay.z == 0.0f){RefractedRay = Reflect(rayDir, normal);}traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, RefractedRay, depth+1, quad,threadindex), refraction);}}}break;case PT_Trigon:{TrigonPrim* trigon = (TrigonPrim*)(traceRes.primitive);traceRes.color = trigon->color;//纹理if(m_enableTexture2D && trigon->pTexture){trigon->SampleTexColor(traceRes.point,texColor,refleraColor,m_texFilter);traceRes.color *= texColor;}//插值法线trigon->SampleNormal(traceRes.point,ptNormal);//光照IlluminatePoint(trigon, traceRes.point, trigon->N, traceRes.color, threadindex);if (depth<MaxTraceDepth){float reflection = trigon->reflection;float refraction = trigon->refraction;//float Eta = trigon->Eta;//float ODEta = trigon->ODEta;//从折射贴图取得折射系数if (trigon->refleraTexture){reflection = refleraColor.r;refraction = refleraColor.g;//Eta = refleraColor.b;//if(Eta>_EPSILON)ODEta = 1/Eta; else ODEta = 99999;}//反射if(m_enableReflection && reflection > 0.0f){vec3 ReflectedRay = Reflect(rayDir, ptNormal);//trigon->N);traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, ReflectedRay, depth+1, trigon,threadindex), reflection);}//todo 球内穿越的距离 会积累球的颜色 类似体积雾//todo 反面要能碰撞检测到//折射 alphaif(m_enableRefraction && refraction > 0.0f){float Angle = -Dot(trigon->N, rayDir);vec3 normal;float Eta;if(Angle > 0.0f){normal = ptNormal;//trigon->N;Eta = trigon->ODEta;}else{normal = -ptNormal;//trigon->N;Eta = trigon->Eta;}vec3 RefractedRay = Refract(rayDir, normal, Eta);if(RefractedRay.x == 0.0f && RefractedRay.y == 0.0f && RefractedRay.z == 0.0f){RefractedRay = Reflect(rayDir, normal);}traceRes.color = Lerp(traceRes.color, TraceRay(traceRes.point, RefractedRay, depth+1, trigon,threadindex), refraction);}}}break;}}return traceRes.color;
}void RayTraceRendDriver::PartionWithBsp(PrimitiveBspTree* bsptree)
{PrimitiveTreeBuilder builder(1,70,true);//16);70PrimitiveBuffRef primitiveBuff(m_primitives,sizeof(QuadPrim*),m_primitivesCount);builder.BuildTree(bsptree,primitiveBuff);//FILE* file = fopen("primitiveTree.txt","wt");//if (file)//{// m_bsptree->Dump(file);// fclose(file);//}
}void RayTraceRendDriver::PartionWithVoxel(UniformVoxelPartion* voxelPartion)
{voxelPartion->Generate(m_primitives,m_primitivesCount,16);//8);//32
}void RayTraceRendDriver::PartionWithLaCone(LaCone3Partion *laConePartion)
{Primitive **EndPrimitive = m_primitives + m_primitivesCount;for(Primitive **pprimitive = m_primitives; pprimitive < EndPrimitive; pprimitive++){laConePartion->GatherPrimtive(*pprimitive);}if (laConePartion->m_primitivesUsedCount>=laConePartion->m_primitivesVolume){MessageBox(0,"laConePartion->m_primitivesUsedCount>=laConePartion->m_primitivesVolume","",MB_OK);Primitive **oldPrimitives = laConePartion->m_primitives;laConePartion->m_primitivesVolume *= 2;laConePartion->m_primitives = new Primitive*[laConePartion->m_primitivesVolume];memcpy(laConePartion->m_primitives,oldPrimitives,laConePartion->m_primitivesUsedCount*sizeof(Primitive*));if(oldPrimitives != NULL){delete [] oldPrimitives;}}laConePartion->m_primitivesUsedCount = 0;laConePartion->AssignLaConeVolume();for(Primitive **pprimitive = m_primitives; pprimitive < EndPrimitive; pprimitive++){laConePartion->PushPrimtive(*pprimitive);}//内部近似深度排序,因为有误差还是要全部遍历 除了traceshadow时可以及时返回
}void RayTraceRendDriver::PartionWithAnguleBox(AnguleBoxPartion *anguleBoxPartion)
{Primitive **EndPrimitive = m_primitives + m_primitivesCount;for(Primitive **pprimitive = m_primitives; pprimitive < EndPrimitive; pprimitive++){anguleBoxPartion->GatherPrimtive(*pprimitive);}if (anguleBoxPartion->m_primitivesUsedCount>=anguleBoxPartion->m_primitivesVolume){MessageBox(0,"laConePartion->m_primitivesUsedCount>=laConePartion->m_primitivesVolume","",MB_OK);Primitive **oldPrimitives = anguleBoxPartion->m_primitives;anguleBoxPartion->m_primitivesVolume *= 2;anguleBoxPartion->m_primitives = new Primitive*[anguleBoxPartion->m_primitivesVolume];memcpy(anguleBoxPartion->m_primitives,oldPrimitives,anguleBoxPartion->m_primitivesUsedCount*sizeof(Primitive*));if(oldPrimitives != NULL){delete [] oldPrimitives;}}anguleBoxPartion->m_primitivesUsedCount = 0;anguleBoxPartion->AssignLaConeVolume();for(Primitive **pprimitive = m_primitives; pprimitive < EndPrimitive; pprimitive++){anguleBoxPartion->PushPrimtive(*pprimitive);}//内部近似深度排序,因为有误差还是要全部遍历 除了traceshadow时可以及时返回
}void RayTraceRendDriver::TagWithBsp(const vec3&pos,const vec3&dir)
{//内部防重复添加m_primitivesTaggedCount=0;m_bspPartion->WalkThroughTray(pos,dir,m_primitivesTagged,m_primitivesTaggedCount);//Primitive **EndPrimitive = m_primitives + m_primitivesCount;//Primitive *primitive;//for(Primitive **pprimitive = m_primitives; pprimitive < EndPrimitive; pprimitive++)//{//   primitive = *pprimitive;// m_primitivesTagged[m_primitivesTaggedCount++] = primitive;//}
}void RayTraceRendDriver::CheckPrimitiveVolume(int addCount)
{if (m_primitivesCount+addCount>=m_primitivesVolume){MessageBox(0,"m_primitivesCount+addCount>=m_primitivesVolume","",MB_OK);Primitive **oldPrimitives = m_primitives;m_primitivesVolume *= 2;m_primitives = new Primitive*[m_primitivesVolume];memcpy(m_primitives,oldPrimitives,m_primitivesCount*sizeof(Primitive*));if(oldPrimitives != NULL){delete [] oldPrimitives;}}
}void RayTraceRendDriver::AddPrimitives(Primitive* pprimitives,int count)
{if (count<=0){return;}CheckPrimitiveVolume(count);PrimitiveType type = pprimitives->primitiveType;int stride = 0;switch(type){case PT_Sphere: stride = sizeof(SpherePrim);break;case PT_Billboard:stride = sizeof(BillboardPrim);break;case PT_Quad:stride = sizeof(QuadPrim);break;case PT_Trigon:stride = sizeof(TrigonPrim);break;}char* head = (char*)pprimitives;Primitive* prim;for (int i=0;i<count;i++){prim = (Primitive*)head;if (prim->primitiveType!=type){MessageBox(0,"primitiveType!=type","",MB_OK);}m_primitives[m_primitivesCount++] = prim;head+=stride;}
}void RayTraceRendDriver::AddPrimitives(Primitive** pprimitives,int count)
{if (count<=0){return;}CheckPrimitiveVolume(count);for (int i=0;i<count;i++){m_primitives[m_primitivesCount++] = *pprimitives;pprimitives++;}
}void RayTraceRendDriver::RemovePrimitives(Primitive* pprimitives,int count)
{if (count<=0){return;}PrimitiveType type = pprimitives->primitiveType;int stride = 0;switch(type){case PT_Sphere: case PT_Billboard:stride = sizeof(SpherePrim);break;case PT_Quad:stride = sizeof(QuadPrim);break;case PT_Trigon:stride = sizeof(TrigonPrim);break;}char* head = (char*)pprimitives;Primitive* prim;for (int i=0;i<count;i++){prim = (Primitive*)head;if (prim->primitiveType!=type){MessageBox(0,"primitiveType!=type","",MB_OK);}//    de *pprimitives;//  pprimitives++;head+=stride;}
}void RayTraceRendDriver::RemovePrimitives(Primitive** pprimitives,int count)
{if (count<=0){return;}for (int i=0;i<count;i++){//   de *pprimitives;//  pprimitives++;}
}void RayTraceRendDriver::DumpPrimitives(Primitive** pprimitives,int count)
{if (count<=0){return;}char buf[512];Primitive* primitive;for (int i=0;i<count;i++){primitive = *pprimitives;switch(primitive->primitiveType){case PT_Sphere: {SpherePrim *sphereprim = (SpherePrim*)primitive;sprintf(buf,"type SpherePrim,center%f,%f,%f  radius%f\n",sphereprim->center.x,sphereprim->center.y,sphereprim->center.z,sphereprim->radius);}break;case PT_Billboard:{BillboardPrim *sphereprim = (BillboardPrim*)primitive;sprintf(buf,"type BillboardPrim,center%f,%f,%f  radius%f\n",sphereprim->center.x,sphereprim->center.y,sphereprim->center.z,sphereprim->radius);}break;case PT_Trigon:{TrigonPrim *trigonprim = (TrigonPrim*)primitive;sprintf(buf,"type TrigonPrim,center%f,%f,%f  radius%f\n",trigonprim->center.x,trigonprim->center.y,trigonprim->center.z,trigonprim->radius);}break;case PT_Quad:{QuadPrim *quadprim = (QuadPrim*)primitive;sprintf(buf,"type PT_Quad,center%f,%f,%f  radius%f\n",quadprim->center.x,quadprim->center.y,quadprim->center.z,quadprim->radius);}break;}OutputDebugString(buf);pprimitives++;}
}bool RayTraceRendDriver::SetQuality(float quality)
{if (m_quality==quality){return false;}m_quality = quality;OnSize(m_wndWidth,m_wndHeight);return true;
}bool RayTraceRendDriver::DrawTextureRect(const RectF& tar)
{int x1 = tar.x;int x2 = tar.x+tar.width;int y1 = tar.y;int y2 = tar.y+tar.height;RayTraceTexture*texture=m_curTexture;x1 = Clamp(x1, 0, m_backbufWidth-1);x2 = Clamp(x2, 0, m_backbufWidth-1);y1 = Clamp(y1, 0, m_backbufHeight-1);y2 = Clamp(y2, 0, m_backbufHeight-1);if (x1 >= x2 || y1 >= y2){return false;}vec3 colorScr(1, 0,0);float invDstWidth = 1.0f/(x2 - x1+1);float invDstHeight = 1.0f/(y2 - y1+1);for (int y = y1;y <= y2;++y){float coordy = float(y - y1) * invDstHeight;BYTE* color_ = m_colorBuffer+(y*m_backbufWidth)*3;vec3* colorHdr = m_hdrColorBuffer+(y*m_backbufWidth);for (int x = x1;x <= x2;++x){float coordx = float(x - x1) *invDstWidth;texture->GetColor11(coordx, coordy,colorScr,m_texFilter);color_[2] = (BYTE)(colorScr.x*255);color_[1] = (BYTE)(colorScr.y*255);color_[0] = (BYTE)(colorScr.z*255);color_+=3;colorHdr->r = colorScr.x;colorHdr->g = colorScr.y;colorHdr->b = colorScr.z;colorHdr++;}}return true;
}

纯c++实现光线追踪渲染器相关推荐

  1. Ray Tracing in One Weekend从零实现一个简单的光线追踪渲染器

    Ray Tracing in One Weekend学习笔记 1.Overview 从零开始实现一个简单的光线追踪渲染器,能够实现漫反射材质.金属材质.透明材质的渲染,此外还实现了摄像机的自由移动和焦 ...

  2. 基于C++与CUDA的N卡GPU并行程序——虚幻5渲染视频很牛逼?让我们从底层C++开始自制光线追踪渲染器,并自制高级版《我的世界》

    虚幻5效果图   哈喽,呆嘎吼.最近5月13日,官方放出了虚幻5的演示视频,据说是可以同屏显示数亿三角形,从而实时渲染出电影级别的画质,其动态光照效果也是极其逼真.其中提到了Nanite技术与Lume ...

  3. 光线追踪渲染实战:蒙特卡洛路径追踪及其c++实现

    项目代码仓库: GitHub:https://github.com/AKGWSB/EzRT gitee:https://gitee.com/AKGWSB/EzRT 目录 写在前面 光线追踪简介 渲染方 ...

  4. 渲染器跑分_碾压图灵43!NVIDIA安培第一个跑分震撼出炉

    NVIDIA Ampere安培架构已经发布两个多月了,相关服务器产品越来越多,但在此之前,我们从未见过它的实际性能数据.现在,全息渲染公司OTOY的CEO Jules Urbach终于满足了我们的好奇 ...

  5. C4D阿诺德Arnold渲染器:C4DtoA mac版(支持c4d r23)

    为大家分享最新激活的C4DtoA for Cinema 4D R23 Mac版,一款高级的蒙特卡洛光线追踪渲染器,由Solid Angle SL 开发,是非常受欢迎的Arnold阿诺德渲染器,此版本需 ...

  6. Arnold阿诺德渲染器:C4DtoA for Cinema4D R20 for Mac

    c4d阿诺德渲染器mac破解版专为Mac用户设计的一款c4d r20插件,专为特征长度动画和视觉效果的需求而打造,与C4D无缝集成:对象(实例,克隆器,变形器,生成器),MoGraph几何体,头发和样 ...

  7. C4D R23插件:阿诺德渲染器C4DtoA

    为大家分享最新激活的C4DtoA for Cinema 4D R23 Mac版,这是非常受欢迎的Arnold阿诺德渲染器,此版本需要安装在Cinema 4D R23中使用,C4D阿诺德Arnold渲染 ...

  8. C4DtoA阿诺德渲染器安装包下载SolidAngle Arnold for Cinema4D R25 Mac安装教程

    SolidAngle Arnold for Cinema4D R25是一款功能强大,深受大家喜欢的蒙特卡洛光线追踪渲染器,旨在满足各类动画视觉效果的需求.C4DtoA阿诺德渲染器Arnold是精心设计 ...

  9. c4d阿诺德渲染器怎么安装?c4d阿诺德渲染器安装激活图文教程

    c4d阿诺德渲染器怎么安装?c4d阿诺德渲染器是一款高级的蒙特卡洛光线追踪渲染器,专为长篇动画和视觉效果的要求而编写.小编现为大家带来c4d r20版本的c4d阿诺德渲染器的详细视频破解教程,感兴趣的 ...

最新文章

  1. 自学python需要买书吗-请问自学 Python 有必要买课程吗?
  2. python crawler(2)
  3. 开发vue用什么ide_VUE项目开发前期需要准备和配置些什么环境?
  4. ninjala还是显示服务器维护,Ninjala更新2.0版本 调整了武器平衡以及BUG修复
  5. [LeetCode] 3Sum
  6. Google的Guava开发库快速快速入门
  7. MATLAB安装错误:Check your internet connection and proxy settings in MATLAB Web preferences
  8. 程序员版本的八荣八耻,爱了
  9. 【Crystal Reports 水晶报表】奇偶行显示不同的颜色 另附CrystalReports常用属性
  10. STM32(3)——外部中断的使用
  11. 大数据的应用场景都有哪些(农业篇)
  12. 面板数据、工具变量选择和Hausman检验的若干问题
  13. Android 从零开始实现微信支付
  14. 网易2018编程题之游历魔法王国
  15. 数据库安全性控制(授权:授予与收回)
  16. android 带头像的弹幕,原生Canvas实现带头像的弹幕
  17. AtCoder Beginner Contest 163 A Circle Pond 圆周率
  18. 关于js延迟加载的几种方法
  19. 外贸鞋店瞄上中高端小区
  20. APPLE越狱软件测试,iOS的越狱检测和反越狱检测剖析

热门文章

  1. Win8 许可证过期怎么重新激活?
  2. Touch ID回归,为用户对苹果最期待功能
  3. [BZOJ4199][NOI2015]品酒大会-后缀数组
  4. 今天鹏鹏会来,待会一起出去买东西。
  5. 安卓逆向(Android)之二__《全民捕鱼》游戏内购破解
  6. OpenCV图像运算+Moviepy实现视频旋转叠加
  7. uniapp小程序实现开屏页
  8. 云存储数据的一般完整性验证
  9. 多个CYUSB3014连接主机时添加序列号
  10. 学编程需要什么基础?