提交 8f2532f0 编写于 作者: H happyfire

- GPU Rasterizer

上级 a4e2e6c3
...@@ -62,8 +62,12 @@ ...@@ -62,8 +62,12 @@
<Compile Include="Assets\URasterizer\Codes\CPURasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\CPURasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\GPURasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\GPURasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\TransformTool.cs" /> <Compile Include="Assets\URasterizer\Codes\TransformTool.cs" />
<None Include="Assets\URasterizer\Shaders\URVertexShader.hlsl" />
<None Include="Assets\URasterizer\DefaultAssets\DefaultShader.shader" /> <None Include="Assets\URasterizer\DefaultAssets\DefaultShader.shader" />
<None Include="Assets\URasterizer\DefaultAssets\URComputeShader.compute" /> <None Include="Assets\URasterizer\Shaders\URCommon.hlsl" />
<None Include="Assets\URasterizer\Shaders\URTriangleProcess.hlsl" />
<None Include="Assets\URasterizer\Shaders\URFragmentShader.hlsl" />
<None Include="Assets\URasterizer\Shaders\URComputeShader.compute" />
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>C:/Program Files/Unity/Hub/Editor/Unity 2020.3.25f1c1/Editor/Data/Managed/UnityEngine/UnityEngine.dll</HintPath> <HintPath>C:/Program Files/Unity/Hub/Editor/Unity 2020.3.25f1c1/Editor/Data/Managed/UnityEngine/UnityEngine.dll</HintPath>
</Reference> </Reference>
......
...@@ -465,6 +465,7 @@ Transform: ...@@ -465,6 +465,7 @@ Transform:
- {fileID: 270156317} - {fileID: 270156317}
- {fileID: 1326646622} - {fileID: 1326646622}
- {fileID: 949938250} - {fileID: 949938250}
- {fileID: 1976593447}
m_Father: {fileID: 1977655288} m_Father: {fileID: 1977655288}
m_RootOrder: 1 m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
...@@ -716,6 +717,102 @@ Animator: ...@@ -716,6 +717,102 @@ Animator:
m_HasTransformHierarchy: 1 m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1 m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorControllerStateOnDisable: 0 m_KeepAnimatorControllerStateOnDisable: 0
--- !u!1 &1976593446
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1976593447}
- component: {fileID: 1976593450}
- component: {fileID: 1976593449}
- component: {fileID: 1976593448}
m_Layer: 0
m_Name: Sphere
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1976593447
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1976593446}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.57, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1651153439}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1976593448
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1976593446}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 275ec1cd091f7d54cb532cf4c552b27a, type: 3}
m_Name:
m_EditorClassIdentifier:
mesh: {fileID: 0}
DoubleSideRendering: 0
--- !u!23 &1976593449
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1976593446}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &1976593450
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1976593446}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &1977655287 --- !u!1 &1977655287
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
......
...@@ -161,7 +161,7 @@ MeshRenderer: ...@@ -161,7 +161,7 @@ MeshRenderer:
m_RenderingLayerMask: 1 m_RenderingLayerMask: 1
m_RendererPriority: 0 m_RendererPriority: 0
m_Materials: m_Materials:
- {fileID: 2100000, guid: f9f96ee2bf6b64945b16abad7a676453, type: 2} - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo: m_StaticBatchInfo:
firstSubMesh: 0 firstSubMesh: 0
subMeshCount: 0 subMeshCount: 0
...@@ -400,7 +400,6 @@ GameObject: ...@@ -400,7 +400,6 @@ GameObject:
- component: {fileID: 1297680263} - component: {fileID: 1297680263}
- component: {fileID: 1297680262} - component: {fileID: 1297680262}
- component: {fileID: 1297680261} - component: {fileID: 1297680261}
- component: {fileID: 1297680260}
- component: {fileID: 1297680264} - component: {fileID: 1297680264}
- component: {fileID: 1297680265} - component: {fileID: 1297680265}
m_Layer: 0 m_Layer: 0
...@@ -410,20 +409,6 @@ GameObject: ...@@ -410,20 +409,6 @@ GameObject:
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 1
--- !u!64 &1297680260
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1297680259}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &1297680261 --- !u!23 &1297680261
MeshRenderer: MeshRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
......
...@@ -13,25 +13,7 @@ namespace URasterizer ...@@ -13,25 +13,7 @@ namespace URasterizer
Matrix4x4 _matModel; Matrix4x4 _matModel;
Matrix4x4 _matView; Matrix4x4 _matView;
Matrix4x4 _matProjection; Matrix4x4 _matProjection;
public Matrix4x4 ModelMatrix
{
get => _matModel;
set => _matModel = value;
}
public Matrix4x4 ViewMatrix
{
get => _matView;
set => _matView = value;
}
public Matrix4x4 ProjectionMatrix
{
get => _matProjection;
set => _matProjection = value;
}
Color[] frame_buf; Color[] frame_buf;
float[] depth_buf; float[] depth_buf;
...@@ -126,7 +108,7 @@ namespace URasterizer ...@@ -126,7 +108,7 @@ namespace URasterizer
public void Clear(BufferMask mask) public void Clear(BufferMask mask)
{ {
ProfileManager.BeginSample("Rasterizer.Clear"); ProfileManager.BeginSample("CPURasterizer.Clear");
if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode) if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode)
{ {
...@@ -156,43 +138,48 @@ namespace URasterizer ...@@ -156,43 +138,48 @@ namespace URasterizer
ProfileManager.EndSample(); ProfileManager.EndSample();
} }
public void SetupViewProjectionMatrix(Camera camera) public void SetupUniforms(Camera camera, Light mainLight)
{ {
//左手坐标系转右手坐标系,以下坐标和向量z取反 switch (_config.FragmentShaderType)
var camPos = camera.transform.position;
camPos.z *= -1;
var lookAt = camera.transform.forward;
lookAt.z *= -1;
var up = camera.transform.up;
up.z *= -1;
ViewMatrix = TransformTool.GetViewMatrix(camPos, lookAt, up);
if (camera.orthographic)
{ {
float halfOrthHeight = camera.orthographicSize; case ShaderType.VertexColor:
float halfOrthWidth = halfOrthHeight * Aspect; CurrentFragmentShader = ShaderContext.FSVertexColor;
float f = -camera.farClipPlane; break;
float n = -camera.nearClipPlane; case ShaderType.BlinnPhong:
ProjectionMatrix = TransformTool.GetOrthographicProjectionMatrix(-halfOrthWidth, halfOrthWidth, -halfOrthHeight, halfOrthHeight, f, n); CurrentFragmentShader = ShaderContext.FSBlinnPhong;
} break;
else case ShaderType.NormalVisual:
{ CurrentFragmentShader = ShaderContext.FSNormalVisual;
ProjectionMatrix = TransformTool.GetPerspectiveProjectionMatrix(camera.fieldOfView, Aspect, camera.nearClipPlane, camera.farClipPlane); break;
default:
CurrentFragmentShader = ShaderContext.FSBlinnPhong;
break;
} }
ShaderContext.Config = _config;
var camPos = camera.transform.position;
camPos.z *= -1;
ShaderContext.Uniforms.WorldSpaceCameraPos = camPos;
var lightDir = mainLight.transform.forward;
lightDir.z *= -1;
ShaderContext.Uniforms.WorldSpaceLightDir = -lightDir;
ShaderContext.Uniforms.LightColor = mainLight.color * mainLight.intensity;
ShaderContext.Uniforms.AmbientColor = _config.AmbientColor;
TransformTool.SetupViewProjectionMatrix(camera, Aspect, out _matView, out _matProjection);
} }
public void Draw(RenderingObject ro, Camera camera) public void DrawObject(RenderingObject ro)
{ {
ProfileManager.BeginSample("Rasterizer.Draw"); ProfileManager.BeginSample("CPURasterizer.DrawObject");
Mesh mesh = ro.mesh; Mesh mesh = ro.mesh;
SetupViewProjectionMatrix(camera); _matModel = ro.GetModelMatrix();
ModelMatrix = ro.GetModelMatrix();
Matrix4x4 mvp = _matProjection * _matView * _matModel; Matrix4x4 mvp = _matProjection * _matView * _matModel;
Matrix4x4 normalMat = _matModel.inverse.transpose; Matrix4x4 normalMat = _matModel.inverse.transpose;
...@@ -533,7 +520,7 @@ namespace URasterizer ...@@ -533,7 +520,7 @@ namespace URasterizer
private void RasterizeWireframe(Triangle t) private void RasterizeWireframe(Triangle t)
{ {
ProfileManager.BeginSample("Rasterizer.RasterizeWireframe"); ProfileManager.BeginSample("CPURasterizer.RasterizeWireframe");
DrawLine(t.Vertex0.Position, t.Vertex1.Position, t.Vertex0.Color, t.Vertex1.Color); DrawLine(t.Vertex0.Position, t.Vertex1.Position, t.Vertex0.Color, t.Vertex1.Color);
DrawLine(t.Vertex1.Position, t.Vertex2.Position, t.Vertex1.Color, t.Vertex2.Color); DrawLine(t.Vertex1.Position, t.Vertex2.Position, t.Vertex1.Color, t.Vertex2.Color);
DrawLine(t.Vertex2.Position, t.Vertex0.Position, t.Vertex2.Color, t.Vertex0.Color); DrawLine(t.Vertex2.Position, t.Vertex0.Position, t.Vertex2.Color, t.Vertex0.Color);
...@@ -547,7 +534,7 @@ namespace URasterizer ...@@ -547,7 +534,7 @@ namespace URasterizer
//Screen space rasterization //Screen space rasterization
void RasterizeTriangle(Triangle t, RenderingObject ro) void RasterizeTriangle(Triangle t, RenderingObject ro)
{ {
ProfileManager.BeginSample("Rasterizer.RasterizeTriangle"); ProfileManager.BeginSample("CPURasterizer.RasterizeTriangle");
var v = _tmpVector4s; var v = _tmpVector4s;
v[0] = t.Vertex0.Position; v[0] = t.Vertex0.Position;
v[1] = t.Vertex1.Position; v[1] = t.Vertex1.Position;
...@@ -703,7 +690,7 @@ namespace URasterizer ...@@ -703,7 +690,7 @@ namespace URasterizer
bool IsInsideTriangle(int x, int y, Triangle t, float offsetX=0.5f, float offsetY=0.5f) bool IsInsideTriangle(int x, int y, Triangle t, float offsetX=0.5f, float offsetY=0.5f)
{ {
ProfileManager.BeginSample("Rasterizer.IsInsideTriangle"); ProfileManager.BeginSample("CPURasterizer.IsInsideTriangle");
var v = _tmpVector3s; var v = _tmpVector3s;
v[0] = new Vector3(t.Vertex0.Position.x, t.Vertex0.Position.y, t.Vertex0.Position.z); v[0] = new Vector3(t.Vertex0.Position.x, t.Vertex0.Position.y, t.Vertex0.Position.z);
v[1] = new Vector3(t.Vertex1.Position.x, t.Vertex1.Position.y, t.Vertex1.Position.z); v[1] = new Vector3(t.Vertex1.Position.x, t.Vertex1.Position.y, t.Vertex1.Position.z);
...@@ -738,7 +725,7 @@ namespace URasterizer ...@@ -738,7 +725,7 @@ namespace URasterizer
Vector3 ComputeBarycentric2D(float x, float y, Triangle t) Vector3 ComputeBarycentric2D(float x, float y, Triangle t)
{ {
ProfileManager.BeginSample("Rasterizer.ComputeBarycentric2D"); ProfileManager.BeginSample("CPURasterizer.ComputeBarycentric2D");
var v = _tmpVector4s; var v = _tmpVector4s;
v[0] = t.Vertex0.Position; v[0] = t.Vertex0.Position;
v[1] = t.Vertex1.Position; v[1] = t.Vertex1.Position;
...@@ -770,7 +757,7 @@ namespace URasterizer ...@@ -770,7 +757,7 @@ namespace URasterizer
public void UpdateFrame() public void UpdateFrame()
{ {
ProfileManager.BeginSample("CameraRenderer.UpdateFrame"); ProfileManager.BeginSample("CPURasterizer.UpdateFrame");
switch (_config.DisplayBuffer) switch (_config.DisplayBuffer)
{ {
......
...@@ -33,7 +33,9 @@ namespace URasterizer ...@@ -33,7 +33,9 @@ namespace URasterizer
private void OnPostRender() private void OnPostRender()
{ {
Render(); if(_config.EnableRendering){
Render();
}
} }
void Init() void Init()
...@@ -88,39 +90,14 @@ namespace URasterizer ...@@ -88,39 +90,14 @@ namespace URasterizer
var r = _rasterizer; var r = _rasterizer;
r.Clear(BufferMask.Color | BufferMask.Depth); r.Clear(BufferMask.Color | BufferMask.Depth);
switch (_config.FragmentShaderType) r.SetupUniforms(_camera, _mainLight);
{
case ShaderType.VertexColor:
r.CurrentFragmentShader = ShaderContext.FSVertexColor;
break;
case ShaderType.BlinnPhong:
r.CurrentFragmentShader = ShaderContext.FSBlinnPhong;
break;
case ShaderType.NormalVisual:
r.CurrentFragmentShader = ShaderContext.FSNormalVisual;
break;
default:
r.CurrentFragmentShader = ShaderContext.FSBlinnPhong;
break;
}
ShaderContext.Config = _config;
var camPos = transform.position;
camPos.z *= -1;
ShaderContext.Uniforms.WorldSpaceCameraPos = camPos;
var lightDir = _mainLight.transform.forward;
lightDir.z *= -1;
ShaderContext.Uniforms.WorldSpaceLightDir = -lightDir;
ShaderContext.Uniforms.LightColor = _mainLight.color * _mainLight.intensity;
ShaderContext.Uniforms.AmbientColor = _config.AmbientColor;
for (int i=0; i<renderingObjects.Count; ++i) for (int i=0; i<renderingObjects.Count; ++i)
{ {
if (renderingObjects[i].gameObject.activeInHierarchy) if (renderingObjects[i].gameObject.activeInHierarchy)
{ {
r.Draw(renderingObjects[i], _camera); r.DrawObject(renderingObjects[i]);
} }
} }
......
...@@ -6,12 +6,13 @@ namespace URasterizer ...@@ -6,12 +6,13 @@ namespace URasterizer
{ {
string Name { get; } string Name { get; }
void Clear(BufferMask mask); void Clear(BufferMask mask);
void Draw(RenderingObject ro, Camera camera);
Texture ColorTexture { get; } void SetupUniforms(Camera camera, Light mainLight);
void DrawObject(RenderingObject ro);
void UpdateFrame(); Texture ColorTexture { get; }
FragmentShader CurrentFragmentShader { get; set; } void UpdateFrame();
} }
} }
\ No newline at end of file
...@@ -6,23 +6,24 @@ namespace URasterizer { ...@@ -6,23 +6,24 @@ namespace URasterizer {
[CreateAssetMenu(menuName = "URasterizer/RenderingConfig")] [CreateAssetMenu(menuName = "URasterizer/RenderingConfig")]
public class RenderingConfig : ScriptableObject public class RenderingConfig : ScriptableObject
{ {
[Header("Common Setting")]
public bool EnableRendering = true;
public Color ClearColor = Color.black; public Color ClearColor = Color.black;
public Color AmbientColor = Color.black;
public RasterizerType RasterizerType;
[Header("CPU Rasterizer ONLY Setting")]
public bool WireframeMode = false; public bool WireframeMode = false;
public bool BackfaceCulling = true; public bool BackfaceCulling = true;
public DisplayBufferType DisplayBuffer = DisplayBufferType.Color; public DisplayBufferType DisplayBuffer = DisplayBufferType.Color;
public MSAALevel MSAA = MSAALevel.Disabled; public MSAALevel MSAA = MSAALevel.Disabled;
public bool BilinearSample = true; public bool BilinearSample = true;
public ShaderType FragmentShaderType = ShaderType.BlinnPhong; public ShaderType FragmentShaderType = ShaderType.BlinnPhong;
public Color AmbientColor = Color.black;
[Header("Vertex Color Setting")]
public VertexColors VertexColors; public VertexColors VertexColors;
[Header("GPU Driven")] [Header("GPU Driven Setting")]
public ComputeShader ComputeShader; public ComputeShader ComputeShader;
[Header("Current Rasterizer")]
public RasterizerType RasterizerType;
} }
public enum DisplayBufferType public enum DisplayBufferType
......
...@@ -10,6 +10,7 @@ namespace URasterizer ...@@ -10,6 +10,7 @@ namespace URasterizer
[HideInInspector, System.NonSerialized] [HideInInspector, System.NonSerialized]
public Texture2D texture; public Texture2D texture;
#region CPU Rasterizer Use
//缓存避免在draw loop中从mesh copy //缓存避免在draw loop中从mesh copy
[HideInInspector, System.NonSerialized] [HideInInspector, System.NonSerialized]
public Vector3[] MeshVertices; public Vector3[] MeshVertices;
...@@ -21,14 +22,17 @@ namespace URasterizer ...@@ -21,14 +22,17 @@ namespace URasterizer
public Vector2[] MeshUVs; public Vector2[] MeshUVs;
[HideInInspector, System.NonSerialized] [HideInInspector, System.NonSerialized]
public VSOutBuf[] vsOutputBuffer; public VSOutBuf[] vsOutputBuffer;
#endregion
#region GPU Rasterizer Use
public ComputeBuffer VertexBuffer; public ComputeBuffer VertexBuffer;
public ComputeBuffer NormalBuffer; public ComputeBuffer NormalBuffer;
public ComputeBuffer UVBuffer;
public ComputeBuffer TriangleBuffer; public ComputeBuffer TriangleBuffer;
public ComputeBuffer VertexOutBuffer; public ComputeBuffer VertexOutBuffer; //for vertex shader output
public ComputeBuffer RenderTriangleBuffer; public ComputeBuffer RenderTriangleBuffer;
#endregion
private void Start() private void Start()
{ {
...@@ -43,7 +47,11 @@ namespace URasterizer ...@@ -43,7 +47,11 @@ namespace URasterizer
{ {
texture = meshRenderer.sharedMaterial.mainTexture as Texture2D; texture = meshRenderer.sharedMaterial.mainTexture as Texture2D;
} }
if(texture==null){
texture = Texture2D.whiteTexture;
}
//CPU Rasterizer使用的模型数据缓存
MeshVertices = mesh.vertices; MeshVertices = mesh.vertices;
MeshNormals = mesh.normals; MeshNormals = mesh.normals;
MeshTriangles = mesh.triangles; MeshTriangles = mesh.triangles;
...@@ -57,23 +65,25 @@ namespace URasterizer ...@@ -57,23 +65,25 @@ namespace URasterizer
NormalBuffer = new ComputeBuffer(vertexCnt, 3*sizeof(float)); NormalBuffer = new ComputeBuffer(vertexCnt, 3*sizeof(float));
NormalBuffer.SetData(MeshNormals); NormalBuffer.SetData(MeshNormals);
UVBuffer = new ComputeBuffer(vertexCnt, 2*sizeof(float));
UVBuffer.SetData(MeshUVs);
//初始化三角形数组,每个三角形包含3个索引值 //初始化三角形数组,每个三角形包含3个索引值
//注意这儿对调了v0和v1的索引,因为原来的 0,1,2是顺时针的,对调后是 1,0,2是逆时针的 //注意这儿对调了v0和v1的索引,因为原来的 0,1,2是顺时针的,对调后是 1,0,2是逆时针的
//Unity Quard模型的两个三角形索引分别是 0,3,1,3,0,2 转换后为 3,0,1,0,3,2 //Unity Quard模型的两个三角形索引分别是 0,3,1,3,0,2 转换后为 3,0,1,0,3,2
int idxCnt = MeshTriangles.Length; int triCnt = MeshTriangles.Length/3;
Vector3Int[] triangles = new Vector3Int[idxCnt/3]; Vector3Int[] triangles = new Vector3Int[triCnt];
for(int i=0; i < triangles.Length; ++i){ for(int i=0; i < triCnt; ++i){
triangles[i].x = MeshTriangles[i*3+1]; int j = i * 3;
triangles[i].y = MeshTriangles[i*3]; triangles[i].x = MeshTriangles[j+1];
triangles[i].z = MeshTriangles[i*3+2]; triangles[i].y = MeshTriangles[j];
triangles[i].z = MeshTriangles[j+2];
} }
TriangleBuffer = new ComputeBuffer(triangles.Length, 3*sizeof(uint)); TriangleBuffer = new ComputeBuffer(triangles.Length, 3*sizeof(uint));
TriangleBuffer.SetData(triangles); TriangleBuffer.SetData(triangles);
VertexOutBuffer = new ComputeBuffer(vertexCnt, 13*sizeof(float)); VertexOutBuffer = new ComputeBuffer(vertexCnt, 15*sizeof(float));
RenderTriangleBuffer = new ComputeBuffer(MeshTriangles.Length/3, sizeof(uint)*3, ComputeBufferType.Append);
} }
void OnDestroy() void OnDestroy()
...@@ -82,12 +92,12 @@ namespace URasterizer ...@@ -82,12 +92,12 @@ namespace URasterizer
VertexBuffer = null; VertexBuffer = null;
NormalBuffer.Release(); NormalBuffer.Release();
NormalBuffer = null; NormalBuffer = null;
VertexOutBuffer.Release(); UVBuffer.Release();
VertexOutBuffer = null; UVBuffer = null;
TriangleBuffer.Release(); TriangleBuffer.Release();
TriangleBuffer = null; TriangleBuffer = null;
RenderTriangleBuffer.Release(); VertexOutBuffer.Release();
RenderTriangleBuffer = null; VertexOutBuffer = null;
} }
......
...@@ -144,6 +144,32 @@ namespace URasterizer ...@@ -144,6 +144,32 @@ namespace URasterizer
float f = -zFar; float f = -zFar;
return GetPerspectiveProjectionMatrix(l, r, b, t, f, n); return GetPerspectiveProjectionMatrix(l, r, b, t, f, n);
} }
public static void SetupViewProjectionMatrix(Camera camera, float aspect, out Matrix4x4 ViewMatrix, out Matrix4x4 ProjectionMatrix)
{
//左手坐标系转右手坐标系,以下坐标和向量z取反
var camPos = camera.transform.position;
camPos.z *= -1;
var lookAt = camera.transform.forward;
lookAt.z *= -1;
var up = camera.transform.up;
up.z *= -1;
ViewMatrix = TransformTool.GetViewMatrix(camPos, lookAt, up);
if (camera.orthographic)
{
float halfOrthHeight = camera.orthographicSize;
float halfOrthWidth = halfOrthHeight * aspect;
float f = -camera.farClipPlane;
float n = -camera.nearClipPlane;
ProjectionMatrix = GetOrthographicProjectionMatrix(-halfOrthWidth, halfOrthWidth, -halfOrthHeight, halfOrthHeight, f, n);
}
else
{
ProjectionMatrix = GetPerspectiveProjectionMatrix(camera.fieldOfView, aspect, camera.nearClipPlane, camera.farClipPlane);
}
}
} }
} }
\ No newline at end of file
...@@ -138,7 +138,7 @@ MonoBehaviour: ...@@ -138,7 +138,7 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Material: {fileID: 0} m_Material: {fileID: 0}
m_Color: {r: 0.36073107, g: 0, b: 0.98039216, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1 m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1 m_Maskable: 1
......
#pragma kernel VertexProcess
#pragma kernel ClearFrame
#pragma kernel TriangleSetup
#pragma kernel RasterizeTriangle
struct VertexOutBuf
{
float4 clipPos;
float3 worldPos;
float3 objectNormal;
float3 worldNormal;
};
float4 ClearColor;
uint2 FrameBufferSize;
float4x4 matMVP;
float4x4 matModel;
uint currentRenderTriangle;
StructuredBuffer<float3> vertexBuffer;
StructuredBuffer<float3> normalBuffer;
RWStructuredBuffer<VertexOutBuf> vertexOutBuffer;
StructuredBuffer<uint3> triangleBuffer; // All triangles of the mesh
AppendStructuredBuffer<uint3> renderTriangleBuffer; //triangles to render
ConsumeStructuredBuffer<uint3> renderCosumeBuffer;
RWTexture2D<float4> frameColorTexture;
[numthreads(32,24,1)]
void ClearFrame(uint3 id : SV_DispatchThreadID)
{
frameColorTexture[id.xy] = ClearColor;
}
[numthreads(768,1,1)]
void VertexProcess (uint3 id : SV_DispatchThreadID)
{
float4 pos = float4(vertexBuffer[id.x].x, vertexBuffer[id.x].y, -vertexBuffer[id.x].z, 1.0f);
float3 normal = float3(normalBuffer[id.x].x, normalBuffer[id.x].y, -normalBuffer[id.x].z);
vertexOutBuffer[id.x].clipPos = mul(matMVP, pos);
vertexOutBuffer[id.x].worldPos = mul(matModel, pos).xyz;
vertexOutBuffer[id.x].objectNormal = normal;
vertexOutBuffer[id.x].worldNormal = mul( (float3x3)matModel , normal);
}
bool Clipped(float4 v[3])
{
//Clip space使用GAMES101规范,右手坐标系,n为+1, f为-1
//裁剪(仅整体剔除)
for (int i = 0; i < 3; ++i)
{
float4 vertex = v[i];
float w = vertex.w;
w = w >= 0 ? w : -w; //由于NDC中总是满足-1<=Zndc<=1, 而当 w < 0 时,-w >= Zclip = Zndc*w >= w。所以此时clip space的坐标范围是[w,-w], 为了比较时更明确,将w取正
bool inside = (vertex.x <= w && vertex.x >= -w
&& vertex.y <= w && vertex.y >= -w
&& vertex.z <= w && vertex.z >= -w);
if (inside)
{
//不裁剪三角形,只要有任意一点在clip space中则三角形整体保留
return false;
}
}
//三个顶点都不在三角形中则剔除
return true;
}
[numthreads(768,1,1)]
void TriangleSetup(uint3 id : SV_DispatchThreadID)
{
uint3 tri = triangleBuffer[id.x];
int idx0 = tri.x;
int idx1 = tri.y;
int idx2 = tri.z;
float4 v[3];
v[0] = vertexOutBuffer[idx0].clipPos;
v[1] = vertexOutBuffer[idx1].clipPos;
v[2] = vertexOutBuffer[idx2].clipPos;
if(Clipped(v)){
return;
}
//Perspective division, clip space to NDC
for (int k=0; k<3; k++)
{
v[k].x /= v[k].w;
v[k].y /= v[k].w;
v[k].z /= v[k].w;
}
//backface culling
float3 e01 = v[1].xyz - v[0].xyz;
float3 e02 = v[2].xyz - v[0].xyz;
float3 crossv = cross(e01, e02);
if (crossv.z < 0)
{
return;
}
//Viewport Transform, NDC to screen space
for (k = 0; k < 3; k++)
{
float4 vec = v[k];
vec.x = 0.5f * FrameBufferSize.x * (vec.x + 1.0f);
vec.y = 0.5f * FrameBufferSize.y * (vec.y + 1.0f);
//在硬件渲染中,NDC的z值经过硬件的透视除法之后就直接写入到depth buffer了,如果要调整需要在投影矩阵中调整
//由于我们是软件渲染,所以可以在这里调整z值。
//GAMES101约定的NDC是右手坐标系,z值范围是[-1,1],但n为1,f为-1,因此值越大越靠近n。
//为了可视化Depth buffer,将最终的z值从[-1,1]映射到[0,1]的范围,因此最终n为1, f为0。离n越近,深度值越大。
//由于远处的z值为0,因此clear时深度要清除为0,然后深度测试时,使用GREATER测试。
//(当然我们也可以在这儿反转z值,然后clear时使用float.MaxValue清除,并且深度测试时使用LESS_EQUAL测试)
//注意:这儿的z值调整并不是必要的,只是为了可视化时便于映射为颜色值。其实也可以在可视化的地方调整。
//但是这么调整后,正好和Unity在DirectX平台的Reverse z一样,让near plane附近的z值的浮点数精度提高。
vec.z = vec.z * 0.5f + 0.5f;
v[k] = vec;
}
//Screen space coordinates saved in clip pos
vertexOutBuffer[idx0].clipPos = v[0];
vertexOutBuffer[idx1].clipPos = v[1];
vertexOutBuffer[idx2].clipPos = v[2];
//triangle actually rendering append to this buffer
renderTriangleBuffer.Append(uint3(idx0, idx1, idx2));
}
float3 ComputeBarycentric2D(float x, float y, float4 v[3])
{
float c1 = (x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * y + v[1].x * v[2].y - v[2].x * v[1].y) / (v[0].x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * v[0].y + v[1].x * v[2].y - v[2].x * v[1].y);
float c2 = (x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * y + v[2].x * v[0].y - v[0].x * v[2].y) / (v[1].x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * v[1].y + v[2].x * v[0].y - v[0].x * v[2].y);
float c3 = (x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * y + v[0].x * v[1].y - v[1].x * v[0].y) / (v[2].x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * v[2].y + v[0].x * v[1].y - v[1].x * v[0].y);
return float3(c1, c2, c3);
}
[numthreads(32,24,1)]
void RasterizeTriangle(uint3 id : SV_DispatchThreadID)
{
uint3 tri = renderCosumeBuffer.Consume();// triangleBuffer[currentRenderTriangle]; //triangleBuffer
int idx0 = tri.x;
int idx1 = tri.y;
int idx2 = tri.z;
float4 v[3];
v[0] = vertexOutBuffer[idx0].clipPos;
v[1] = vertexOutBuffer[idx1].clipPos;
v[2] = vertexOutBuffer[idx2].clipPos;
//这个函数,每个像素都会执行,最好用一个buffer存所有的需要渲染的三角形的AABB,避免每次都在这儿计算
//Find out the bounding box of current triangle.
float minX = v[0].x;
float maxX = minX;
float minY = v[0].y;
float maxY = minY;
for(int i=1; i<3; ++i)
{
float x = v[i].x;
if(x < minX)
{
minX = x;
} else if(x > maxX)
{
maxX = x;
}
float y = v[i].y;
if(y < minY)
{
minY = y;
}else if(y > maxY)
{
maxY = y;
}
}
int minPX = floor(minX);
minPX = minPX < 0 ? 0 : minPX;
int maxPX = ceil(maxX);
maxPX = maxPX > FrameBufferSize.x ? FrameBufferSize.x : maxPX;
int minPY = floor(minY);
minPY = minPY < 0 ? 0 : minPY;
int maxPY = ceil(maxY);
maxPY = maxPY > FrameBufferSize.y ? FrameBufferSize.y : maxPY;
//判断当前像素是否在AABB中
if(id.x < minPX || id.x > maxPX || id.y < minPY || id.y > maxPY){
return;
}
int x = id.x;
int y = id.y;
//计算重心坐标
float3 c = ComputeBarycentric2D(x, y, v);
float alpha = c.x;
float beta = c.y;
float gamma = c.z;
if(alpha < 0 || beta < 0 || gamma < 0){
return;
}
//透视校正插值,z为透视校正插值后的view space z值
float z = 1.0f / (alpha / v[0].w + beta / v[1].w + gamma / v[2].w);
//zp为透视校正插值后的screen space z值
float zp = (alpha * v[0].z / v[0].w + beta * v[1].z / v[1].w + gamma * v[2].z / v[2].w) * z;
//深度测试(注意我们这儿的z值越大越靠近near plane,因此大值通过测试)
//if(zp >= depth_buf[index])
//depth_buf[index] = zp;
//透视校正插值
//float3 color_p = (alpha * t.Vertex0.Color / v[0].w + beta * t.Vertex1.Color / v[1].w + gamma * t.Vertex2.Color / v[2].w) * z;
//Vector2 uv_p = (alpha * t.Vertex0.Texcoord / v[0].w + beta * t.Vertex1.Texcoord / v[1].w + gamma * t.Vertex2.Texcoord / v[2].w) * z;
//Vector3 normal_p = (alpha * t.Vertex0.Normal / v[0].w + beta * t.Vertex1.Normal / v[1].w + gamma * t.Vertex2.Normal / v[2].w) * z;
//Vector3 worldPos_p = (alpha * t.Vertex0.WorldPos / v[0].w + beta * t.Vertex1.WorldPos / v[1].w + gamma * t.Vertex2.WorldPos / v[2].w) * z;
//Vector3 worldNormal_p = (alpha * t.Vertex0.WorldNormal / v[0].w + beta * t.Vertex1.WorldNormal / v[1].w + gamma * t.Vertex2.WorldNormal / v[2].w) * z;
//if (CurrentFragmentShader != null)
{
//FragmentShaderInputData input = new FragmentShaderInputData();
//input.Color = color_p;
//input.UV = uv_p;
//input.Texture = ro.texture;
//input.LocalNormal = normal_p;
//input.WorldPos = worldPos_p;
//input.WorldNormal = worldNormal_p;
frameColorTexture[id.xy] = float4(1,1,1,1);
}
}
// void RasterizeTriangle(Triangle t, RenderingObject ro)
// {
// ProfileManager.BeginSample("Rasterizer.RasterizeTriangle");
// var v = _tmpVector4s;
// v[0] = t.Vertex0.Position;
// v[1] = t.Vertex1.Position;
// v[2] = t.Vertex2.Position;
// //Find out the bounding box of current triangle.
// float minX = v[0].x;
// float maxX = minX;
// float minY = v[0].y;
// float maxY = minY;
// for(int i=1; i<3; ++i)
// {
// float x = v[i].x;
// if(x < minX)
// {
// minX = x;
// } else if(x > maxX)
// {
// maxX = x;
// }
// float y = v[i].y;
// if(y < minY)
// {
// minY = y;
// }else if(y > maxY)
// {
// maxY = y;
// }
// }
// int minPX = Mathf.FloorToInt(minX);
// minPX = minPX < 0 ? 0 : minPX;
// int maxPX = Mathf.CeilToInt(maxX);
// maxPX = maxPX > _width ? _width : maxPX;
// int minPY = Mathf.FloorToInt(minY);
// minPY = minPY < 0 ? 0 : minPY;
// int maxPY = Mathf.CeilToInt(maxY);
// maxPY = maxPY > _height ? _height : maxPY;
// if(_config.MSAA == MSAALevel.Disabled)
// {
// // 遍历当前三角形包围中的所有像素,判断当前像素是否在三角形中
// // 对于在三角形中的像素,使用重心坐标插值得到深度值,并使用z buffer进行深度测试和写入
// for(int y = minPY; y < maxPY; ++y)
// {
// for(int x = minPX; x < maxPX; ++x)
// {
// //if(IsInsideTriangle(x, y, t)) //-->检测是否在三角形内比使用重心坐标检测要慢,因此先计算重心坐标,再检查3个坐标是否有小于0
// {
// //计算重心坐标
// var c = ComputeBarycentric2D(x, y, t);
// float alpha = c.x;
// float beta = c.y;
// float gamma = c.z;
// if(alpha < 0 || beta < 0 || gamma < 0){
// continue;
// }
// //透视校正插值,z为透视校正插值后的view space z值
// float z = 1.0f / (alpha / v[0].w + beta / v[1].w + gamma / v[2].w);
// //zp为透视校正插值后的screen space z值
// float zp = (alpha * v[0].z / v[0].w + beta * v[1].z / v[1].w + gamma * v[2].z / v[2].w) * z;
// //深度测试(注意我们这儿的z值越大越靠近near plane,因此大值通过测试)
// int index = GetIndex(x, y);
// if(zp >= depth_buf[index])
// {
// depth_buf[index] = zp;
// //透视校正插值
// ProfileManager.BeginSample("Rasterizer.RasterizeTriangle.AttributeInterpolation");
// Color color_p = (alpha * t.Vertex0.Color / v[0].w + beta * t.Vertex1.Color / v[1].w + gamma * t.Vertex2.Color / v[2].w) * z;
// Vector2 uv_p = (alpha * t.Vertex0.Texcoord / v[0].w + beta * t.Vertex1.Texcoord / v[1].w + gamma * t.Vertex2.Texcoord / v[2].w) * z;
// Vector3 normal_p = (alpha * t.Vertex0.Normal / v[0].w + beta * t.Vertex1.Normal / v[1].w + gamma * t.Vertex2.Normal / v[2].w) * z;
// Vector3 worldPos_p = (alpha * t.Vertex0.WorldPos / v[0].w + beta * t.Vertex1.WorldPos / v[1].w + gamma * t.Vertex2.WorldPos / v[2].w) * z;
// Vector3 worldNormal_p = (alpha * t.Vertex0.WorldNormal / v[0].w + beta * t.Vertex1.WorldNormal / v[1].w + gamma * t.Vertex2.WorldNormal / v[2].w) * z;
// ProfileManager.EndSample();
// if (CurrentFragmentShader != null)
// {
// FragmentShaderInputData input = new FragmentShaderInputData();
// input.Color = color_p;
// input.UV = uv_p;
// input.Texture = ro.texture;
// input.LocalNormal = normal_p;
// input.WorldPos = worldPos_p;
// input.WorldNormal = worldNormal_p;
// ProfileManager.BeginSample("Rasterizer.RasterizeTriangle.FragmentShader");
// frame_buf[index] = CurrentFragmentShader(input);
// ProfileManager.EndSample();
// }
// }
// }
// }
// }
// }
// ProfileManager.EndSample();
// }
...@@ -12,14 +12,14 @@ MonoBehaviour: ...@@ -12,14 +12,14 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5fa123a60a768444af03a384cb34a74, type: 3} m_Script: {fileID: 11500000, guid: d5fa123a60a768444af03a384cb34a74, type: 3}
m_Name: RenderingConfig m_Name: RenderingConfig
m_EditorClassIdentifier: m_EditorClassIdentifier:
ClearColor: {r: 0.056692798, g: 0.41403675, b: 0.9245283, a: 0.24705882} ClearColor: {r: 0, g: 0, b: 0, a: 1}
AmbientColor: {r: 0.0754717, g: 0.0754717, b: 0.0754717, a: 1}
RasterizerType: 1
WireframeMode: 0 WireframeMode: 0
BackfaceCulling: 1 BackfaceCulling: 1
DisplayBuffer: 0 DisplayBuffer: 0
MSAA: 0 MSAA: 0
BilinearSample: 1 BilinearSample: 1
FragmentShaderType: 1 FragmentShaderType: 1
AmbientColor: {r: 0.0754717, g: 0.075044505, b: 0.075044505, a: 1}
VertexColors: {fileID: 11400000, guid: a126a2fdc8a60c54e8a3aadb7db4bb3a, type: 2} VertexColors: {fileID: 11400000, guid: a126a2fdc8a60c54e8a3aadb7db4bb3a, type: 2}
ComputeShader: {fileID: 7200000, guid: caa96f337395ad9449e1be41546efcd6, type: 3} ComputeShader: {fileID: 7200000, guid: caa96f337395ad9449e1be41546efcd6, type: 3}
RasterizerType: 1
fileFormatVersion: 2
guid: db6144c7af5ba0a43b63a0a8e34a1cad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
struct VertexOutBuf
{
float4 clipPos;
float3 worldPos;
float3 objectNormal;
float3 worldNormal;
float2 uv;
};
float4 clearColor;
int2 frameBufferSize;
float4x4 matMVP;
float4x4 matModel;
float3 worldSpaceCameraPos;
float3 worldSpaceLightDir;
float4 lightColor;
float4 ambientColor;
StructuredBuffer<float3> vertexBuffer;
StructuredBuffer<float3> normalBuffer;
StructuredBuffer<float2> uvBuffer;
StructuredBuffer<uint3> triangleBuffer; // All triangles of the mesh
RWStructuredBuffer<VertexOutBuf> vertexOutBuffer;
RWTexture2D<float4> frameColorTexture;
RWTexture2D<float> frameDepthTexture;
fileFormatVersion: 2
guid: 252a3b656c0fa814fb91d0ef851fb108
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#pragma kernel VertexProcess
#pragma kernel ClearFrame
#pragma kernel TriangleProcess
#include "URCommon.hlsl"
#include "URVertexShader.hlsl"
#include "URFragmentShader.hlsl"
#include "URTriangleProcess.hlsl"
[numthreads(32,24,1)]
void ClearFrame(uint3 id : SV_DispatchThreadID)
{
frameColorTexture[id.xy] = clearColor;
frameDepthTexture[id.xy] = 0;
}
[numthreads(512,1,1)]
void VertexProcess (uint3 id : SV_DispatchThreadID)
{
VertexTransform(id.x);
}
[numthreads(512,1,1)]
void TriangleProcess(uint3 id : SV_DispatchThreadID)
{
uint3 tri = triangleBuffer[id.x];
int idx0 = tri.x;
int idx1 = tri.y;
int idx2 = tri.z;
float4 v[3];
v[0] = vertexOutBuffer[idx0].clipPos;
v[1] = vertexOutBuffer[idx1].clipPos;
v[2] = vertexOutBuffer[idx2].clipPos;
if(Clipped(v)){
return;
}
//Perspective division, clip space to NDC
for (int k=0; k<3; k++)
{
v[k].x /= v[k].w;
v[k].y /= v[k].w;
v[k].z /= v[k].w;
}
//backface culling
float3 e01 = v[1].xyz - v[0].xyz;
float3 e02 = v[2].xyz - v[0].xyz;
float3 crossv = cross(e01, e02);
if (crossv.z < 0)
{
return;
}
//Viewport Transform, NDC to screen space
for (k = 0; k < 3; k++)
{
float4 vec = v[k];
vec.x = 0.5f * frameBufferSize.x * (vec.x + 1.0f);
vec.y = 0.5f * frameBufferSize.y * (vec.y + 1.0f);
//在硬件渲染中,NDC的z值经过硬件的透视除法之后就直接写入到depth buffer了,如果要调整需要在投影矩阵中调整
//由于我们是软件渲染,所以可以在这里调整z值。
//GAMES101约定的NDC是右手坐标系,z值范围是[-1,1],但n为1,f为-1,因此值越大越靠近n。
//为了可视化Depth buffer,将最终的z值从[-1,1]映射到[0,1]的范围,因此最终n为1, f为0。离n越近,深度值越大。
//由于远处的z值为0,因此clear时深度要清除为0,然后深度测试时,使用GREATER测试。
//(当然我们也可以在这儿反转z值,然后clear时使用float.MaxValue清除,并且深度测试时使用LESS_EQUAL测试)
//注意:这儿的z值调整并不是必要的,只是为了可视化时便于映射为颜色值。其实也可以在可视化的地方调整。
//但是这么调整后,正好和Unity在DirectX平台的Reverse z一样,让near plane附近的z值的浮点数精度提高。
vec.z = vec.z * 0.5f + 0.5f;
v[k] = vec;
}
RasterizeTriangle(idx0, idx1, idx2, v);
}
Texture2D<float4> meshTexture;
SamplerState samplermeshTexture;
float4 FSBlinnPhong(float3 worldPos, float3 worldNormal, float2 uv)
{
float4 textureColor = meshTexture.SampleLevel(samplermeshTexture, uv, 0); //Compute shader中不能使用Sample
float4 ks = float4(0.7937f, 0.7937f, 0.7937f, 1.0f);
float ndotl = dot(worldNormal, worldSpaceLightDir);
float4 diffuse = textureColor * lightColor * saturate(ndotl);
float3 viewDir = normalize(worldSpaceCameraPos - worldPos);
float3 halfDir = normalize(viewDir + worldSpaceLightDir);
float hdotn = dot(halfDir, worldNormal);
float4 specular = ks * lightColor * pow(saturate(hdotn), 150);
return ambientColor + diffuse + specular;
}
fileFormatVersion: 2
guid: 6abde8a54e513cd42950ae3ee5bb48ec
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
bool Clipped(float4 v[3])
{
//Clip space使用GAMES101规范,右手坐标系,n为+1, f为-1
//裁剪(仅整体剔除)
for (int i = 0; i < 3; ++i)
{
float4 vertex = v[i];
float w = vertex.w;
w = w >= 0 ? w : -w; //由于NDC中总是满足-1<=Zndc<=1, 而当 w < 0 时,-w >= Zclip = Zndc*w >= w。所以此时clip space的坐标范围是[w,-w], 为了比较时更明确,将w取正
bool inside = (vertex.x <= w && vertex.x >= -w
&& vertex.y <= w && vertex.y >= -w
&& vertex.z <= w && vertex.z >= -w);
if (inside)
{
//不裁剪三角形,只要有任意一点在clip space中则三角形整体保留
return false;
}
}
//三个顶点都不在三角形中则剔除
return true;
}
float3 ComputeBarycentric2D(float x, float y, float4 v[3])
{
float c1 = (x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * y + v[1].x * v[2].y - v[2].x * v[1].y) / (v[0].x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * v[0].y + v[1].x * v[2].y - v[2].x * v[1].y);
float c2 = (x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * y + v[2].x * v[0].y - v[0].x * v[2].y) / (v[1].x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * v[1].y + v[2].x * v[0].y - v[0].x * v[2].y);
float c3 = (x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * y + v[0].x * v[1].y - v[1].x * v[0].y) / (v[2].x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * v[2].y + v[0].x * v[1].y - v[1].x * v[0].y);
return float3(c1, c2, c3);
}
//v: screen space vertex coordinates
void RasterizeTriangle(int idx0, int idx1, int idx2, float4 v[3])
{
//Find out the bounding box of current triangle.
float minX = v[0].x;
float maxX = minX;
float minY = v[0].y;
float maxY = minY;
for(int i=1; i<3; ++i)
{
float x = v[i].x;
if(x < minX)
{
minX = x;
} else if(x > maxX)
{
maxX = x;
}
float y = v[i].y;
if(y < minY)
{
minY = y;
}else if(y > maxY)
{
maxY = y;
}
}
int minPX = floor(minX);
minPX = minPX < 0 ? 0 : minPX;
int maxPX = ceil(maxX);
maxPX = maxPX > frameBufferSize.x ? frameBufferSize.x : maxPX;
int minPY = floor(minY);
minPY = minPY < 0 ? 0 : minPY;
int maxPY = ceil(maxY);
maxPY = maxPY > frameBufferSize.y ? frameBufferSize.y : maxPY;
VertexOutBuf vertex0 = vertexOutBuffer[idx0];
VertexOutBuf vertex1 = vertexOutBuffer[idx1];
VertexOutBuf vertex2 = vertexOutBuffer[idx2];
for(int y = minPY; y < maxPY; ++y)
{
for(int x = minPX; x < maxPX; ++x)
{
//计算重心坐标
float3 c = ComputeBarycentric2D(x, y, v);
float alpha = c.x;
float beta = c.y;
float gamma = c.z;
if(alpha < 0 || beta < 0 || gamma < 0){
continue;
}
//透视校正插值,z为透视校正插值后的view space z值
float z = 1.0f / (alpha / v[0].w + beta / v[1].w + gamma / v[2].w);
//zp为透视校正插值后的screen space z值
float zp = (alpha * v[0].z / v[0].w + beta * v[1].z / v[1].w + gamma * v[2].z / v[2].w) * z;
//深度测试(注意我们这儿的z值越大越靠近near plane,因此大值通过测试)
if(zp > frameDepthTexture[uint2(x,y)])
{
frameDepthTexture[uint2(x,y)] = zp;
//透视校正插值
//float3 color_p = (alpha * t.Vertex0.Color / v[0].w + beta * t.Vertex1.Color / v[1].w + gamma * t.Vertex2.Color / v[2].w) * z;
float2 uv_p = (alpha * vertex0.uv / v[0].w + beta * vertex1.uv / v[1].w + gamma * vertex2.uv / v[2].w) * z;
float3 normal_p = (alpha * vertex0.objectNormal / v[0].w + beta * vertex1.objectNormal / v[1].w + gamma * vertex2.objectNormal / v[2].w) * z;
float3 worldPos_p = (alpha * vertex0.worldPos / v[0].w + beta * vertex1.worldPos / v[1].w + gamma * vertex2.worldPos / v[2].w) * z;
float3 worldNormal_p = (alpha * vertex0.worldNormal / v[0].w + beta * vertex1.worldNormal / v[1].w + gamma * vertex2.worldNormal / v[2].w) * z;
frameColorTexture[uint2(x,y)] = FSBlinnPhong(worldPos_p, worldNormal_p, uv_p);
}
}
}
}
fileFormatVersion: 2
guid: 85e2d77fa024824419b563f193a7472e
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
void VertexTransform (uint vertexIdx)
{
float4 pos = float4(vertexBuffer[vertexIdx].x, vertexBuffer[vertexIdx].y, -vertexBuffer[vertexIdx].z, 1.0f);
float3 normal = float3(normalBuffer[vertexIdx].x, normalBuffer[vertexIdx].y, -normalBuffer[vertexIdx].z);
vertexOutBuffer[vertexIdx].clipPos = mul(matMVP, pos);
vertexOutBuffer[vertexIdx].worldPos = mul(matModel, pos).xyz;
vertexOutBuffer[vertexIdx].objectNormal = normal;
vertexOutBuffer[vertexIdx].worldNormal = mul( (float3x3)matModel , normal);
vertexOutBuffer[vertexIdx].uv = uvBuffer[vertexIdx];
}
\ No newline at end of file
fileFormatVersion: 2
guid: 436233d9a8473544e826c6008e7b2e3f
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册