提交 15bccf0d 编写于 作者: H happyfire

- refractor code

- Job system
上级 beaacaed
...@@ -41,22 +41,24 @@ ...@@ -41,22 +41,24 @@
<Compile Include="Assets\URasterizer\Codes\Common\ProfileManager.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\ProfileManager.cs" />
<Compile Include="Assets\URasterizer\Codes\IRasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\IRasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\CPURasterizer\FragmentShader.cs" /> <Compile Include="Assets\URasterizer\Codes\CPURasterizer\FragmentShader.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\TriangleJob.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\IRenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\JobRenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\CommonDef.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\CommonDef.cs" />
<Compile Include="Assets\URasterizer\Codes\RenderingObject.cs" /> <Compile Include="Assets\URasterizer\Codes\RenderingObject.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\VertexColors.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\VertexColors.cs" />
<Compile Include="Assets\URasterizer\Codes\RenderingConfig.cs" /> <Compile Include="Assets\URasterizer\Codes\RenderingConfig.cs" />
<Compile Include="Assets\URasterizer\Codes\GPURasterizer\GPURenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\StatsPanel.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\StatsPanel.cs" />
<Compile Include="Assets\URasterizer\Codes\CPURasterizer\CPURenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\CameraRenderer.cs" /> <Compile Include="Assets\URasterizer\Codes\CameraRenderer.cs" />
<Compile Include="Assets\URasterizer\Codes\CPURasterizer\Triangle.cs" /> <Compile Include="Assets\URasterizer\Codes\CPURasterizer\Triangle.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\JobRasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\CPURasterizer\CPURasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\CPURasterizer\CPURasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\GPURasterizer\GPURasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\GPURasterizer\GPURasterizer.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\TransformTool.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\TransformTool.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\JobRasterizer.cs" /> <Compile Include="Assets\URasterizer\Codes\Common\URUtils.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\RasterJobs.cs" /> <Compile Include="Assets\URasterizer\Codes\JobRasterizer\VertexJob.cs" />
<Compile Include="Assets\URasterizer\Codes\CPURasterizer\CPURenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\Common\IRenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\GPURasterizer\GPURenderObjectData.cs" />
<Compile Include="Assets\URasterizer\Codes\JobRasterizer\JobRenderObjectData.cs" />
<None Include="Assets\URasterizer\Shaders\URVertexShader.hlsl" /> <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\Shaders\URCommon.hlsl" /> <None Include="Assets\URasterizer\Shaders\URCommon.hlsl" />
......
...@@ -67,7 +67,7 @@ TextureImporter: ...@@ -67,7 +67,7 @@ TextureImporter:
buildTarget: DefaultTexturePlatform buildTarget: DefaultTexturePlatform
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
...@@ -79,7 +79,7 @@ TextureImporter: ...@@ -79,7 +79,7 @@ TextureImporter:
buildTarget: Standalone buildTarget: Standalone
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
......
...@@ -67,7 +67,7 @@ TextureImporter: ...@@ -67,7 +67,7 @@ TextureImporter:
buildTarget: DefaultTexturePlatform buildTarget: DefaultTexturePlatform
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
...@@ -79,7 +79,7 @@ TextureImporter: ...@@ -79,7 +79,7 @@ TextureImporter:
buildTarget: Standalone buildTarget: Standalone
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
......
...@@ -67,7 +67,7 @@ TextureImporter: ...@@ -67,7 +67,7 @@ TextureImporter:
buildTarget: DefaultTexturePlatform buildTarget: DefaultTexturePlatform
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
...@@ -79,7 +79,7 @@ TextureImporter: ...@@ -79,7 +79,7 @@ TextureImporter:
buildTarget: Standalone buildTarget: Standalone
maxTextureSize: 2048 maxTextureSize: 2048
resizeAlgorithm: 0 resizeAlgorithm: 0
textureFormat: -1 textureFormat: 3
textureCompression: 1 textureCompression: 1
compressionQuality: 50 compressionQuality: 50
crunchedCompression: 0 crunchedCompression: 0
......
...@@ -405,7 +405,7 @@ PrefabInstance: ...@@ -405,7 +405,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3} - target: {fileID: 919132149155446097, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3}
propertyPath: m_IsActive propertyPath: m_IsActive
value: 1 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3}
...@@ -631,7 +631,7 @@ PrefabInstance: ...@@ -631,7 +631,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3} - target: {fileID: 919132149155446097, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3}
propertyPath: m_IsActive propertyPath: m_IsActive
value: 1 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 0b4771b06a3a8614b822c760aaba2a18, type: 3}
......
...@@ -34,8 +34,7 @@ namespace URasterizer ...@@ -34,8 +34,7 @@ namespace URasterizer
public OnRasterizerStatUpdate StatDelegate; public OnRasterizerStatUpdate StatDelegate;
//优化GC //优化GC
Vector4[] _tmpVector4s = new Vector4[3]; Vector4[] _tmpVector4s = new Vector4[3];
Vector4[] _tmp8Vector4s = new Vector4[8];
Vector3[] _tmpVector3s = new Vector3[3]; Vector3[] _tmpVector3s = new Vector3[3];
public String Name { get=>"CPU"; } public String Name { get=>"CPU"; }
...@@ -77,6 +76,17 @@ namespace URasterizer ...@@ -77,6 +76,17 @@ namespace URasterizer
} }
} }
public void Release()
{
texture = null;
frame_buf = null;
depth_buf = null;
temp_buf = null;
samplers_color_MSAA = null;
samplers_mask_MSAA = null;
samplers_depth_MSAA = null;
}
public float Aspect public float Aspect
{ {
get get
...@@ -85,27 +95,7 @@ namespace URasterizer ...@@ -85,27 +95,7 @@ namespace URasterizer
} }
} }
void FillArray<T>(T[] arr, T value)
{
int i = 0;
if(arr.Length > 16)
{
do
{
arr[i++] = value;
} while (i < arr.Length);
while( i + 16 < arr.Length)
{
Array.Copy(arr, 0, arr, i, 16);
i += 16;
}
}
while (i < arr.Length)
{
arr[i++] = value;
}
}
public void Clear(BufferMask mask) public void Clear(BufferMask mask)
{ {
...@@ -118,19 +108,19 @@ namespace URasterizer ...@@ -118,19 +108,19 @@ namespace URasterizer
if ((mask & BufferMask.Color) == BufferMask.Color) if ((mask & BufferMask.Color) == BufferMask.Color)
{ {
FillArray(frame_buf, _config.ClearColor); URUtils.FillArray(frame_buf, _config.ClearColor);
if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode) if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode)
{ {
FillArray(samplers_color_MSAA, _config.ClearColor); URUtils.FillArray(samplers_color_MSAA, _config.ClearColor);
FillArray(samplers_mask_MSAA, false); URUtils.FillArray(samplers_mask_MSAA, false);
} }
} }
if((mask & BufferMask.Depth) == BufferMask.Depth) if((mask & BufferMask.Depth) == BufferMask.Depth)
{ {
FillArray(depth_buf, 0f); URUtils.FillArray(depth_buf, 0f);
if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode) if (_config.MSAA != MSAALevel.Disabled && !_config.WireframeMode)
{ {
FillArray(samplers_depth_MSAA, 0f); URUtils.FillArray(samplers_depth_MSAA, 0f);
} }
} }
...@@ -174,99 +164,7 @@ namespace URasterizer ...@@ -174,99 +164,7 @@ namespace URasterizer
TransformTool.SetupViewProjectionMatrix(camera, Aspect, out _matView, out _matProjection); TransformTool.SetupViewProjectionMatrix(camera, Aspect, out _matView, out _matProjection);
} }
//在ClipSpace中,判断OBB顶点是否在视锥外部。输入v为clip space下OBB的8个顶点
//该函数使用的是保守视锥剔除算法,对于每个裁剪面都检查OBB的所有顶点是否在它外面,如果都在则剔除
//该算法是保守的,不会错误剔除掉不该剔除的OBB,但是可能有一些特殊位置的OBB剔除不掉,
//比如当OBB比较大且在视锥外,但是同时和左右近3个面相交,这样这3个面就无法成功判断剔除。
//这种情况一般是离镜头很近的大的墙体,可能会剔除不掉,造成性能问题。
//可参考:https://www.iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
bool CheckVerticesOutFrustumClipSpace(Vector4[] v)
{
//left
int cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].x < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//right
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].x > w){
++cnt;
}
if(cnt==8){
return true;
}
}
//bottom
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].y < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//top
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].y > w){
++cnt;
}
if(cnt==8){
return true;
}
}
//near
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].z < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//far
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].z > w){
++cnt;
}
if(cnt==8){
return true;
}
}
return false;
}
bool FrustumCulling(Bounds localAABB, Matrix4x4 mvp)
{
var v = _tmp8Vector4s;
var min = localAABB.min; min.z = -min.z;
var max = localAABB.max; max.z = -max.z;
v[0] = mvp * new Vector4(min.x, min.y, min.z, 1.0f);
v[1] = mvp * new Vector4(min.x, min.y, max.z, 1.0f);
v[2] = mvp * new Vector4(min.x, max.y, min.z, 1.0f);
v[3] = mvp * new Vector4(min.x, max.y, max.z, 1.0f);
v[4] = mvp * new Vector4(max.x, min.y, min.z, 1.0f);
v[5] = mvp * new Vector4(max.x, min.y, max.z, 1.0f);
v[6] = mvp * new Vector4(max.x, max.y, min.z, 1.0f);
v[7] = mvp * new Vector4(max.x, max.y, max.z, 1.0f);
return CheckVerticesOutFrustumClipSpace(v);
}
public void DrawObject(RenderingObject ro) public void DrawObject(RenderingObject ro)
{ {
...@@ -277,7 +175,7 @@ namespace URasterizer ...@@ -277,7 +175,7 @@ namespace URasterizer
_matModel = ro.GetModelMatrix(); _matModel = ro.GetModelMatrix();
Matrix4x4 mvp = _matProjection * _matView * _matModel; Matrix4x4 mvp = _matProjection * _matView * _matModel;
if(_config.FrustumCulling && FrustumCulling(mesh.bounds, mvp)){ if(_config.FrustumCulling && URUtils.FrustumCulling(mesh.bounds, mvp)){
ProfileManager.EndSample(); ProfileManager.EndSample();
return; return;
} }
...@@ -761,7 +659,9 @@ namespace URasterizer ...@@ -761,7 +659,9 @@ namespace URasterizer
FragmentShaderInputData input = new FragmentShaderInputData(); FragmentShaderInputData input = new FragmentShaderInputData();
input.Color = color_p; input.Color = color_p;
input.UV = uv_p; input.UV = uv_p;
input.Texture = ro.texture; input.TextureData = ro.texture.GetPixelData<URColor24>(0);
input.TextureWidth = ro.texture.width;
input.TextureHeight = ro.texture.height;
input.LocalNormal = normal_p; input.LocalNormal = normal_p;
input.WorldPos = worldPos_p; input.WorldPos = worldPos_p;
input.WorldNormal = worldNormal_p; input.WorldNormal = worldNormal_p;
......
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Unity.Collections;
namespace URasterizer namespace URasterizer
{ {
//Shader在世界空间下计算 //Shader在世界空间下计算
public struct URColor24
{
public byte r;
public byte g;
public byte b;
public static implicit operator Color(URColor24 c)
{
float s = 1/255f;
return new Color(c.r * s, c.g * s, c.b * s, 1);
}
}
public struct FragmentShaderInputData public struct FragmentShaderInputData
{ {
public Vector3 WorldPos; public Vector3 WorldPos;
public Vector3 WorldNormal; public Vector3 WorldNormal;
public Vector3 LocalNormal; public Vector3 LocalNormal;
public Color Color; public Color Color;
public Vector2 UV; public Vector2 UV;
public Texture2D Texture; public NativeArray<URColor24> TextureData; //因为我们的纹理都是RGB格式的(24位),所以不能用Color32(32位)
public int TextureWidth;
public int TextureHeight;
} }
public struct ShaderUniforms public struct ShaderUniforms
...@@ -45,21 +61,29 @@ namespace URasterizer ...@@ -45,21 +61,29 @@ namespace URasterizer
public static Color FSBlinnPhong(FragmentShaderInputData input) public static Color FSBlinnPhong(FragmentShaderInputData input)
{ {
Color textureColor = Color.white;
if (input.Texture != null) int w = input.TextureWidth;
{ int h = input.TextureHeight;
int w = input.Texture.width; int x = (int)(w * input.UV.x);
int h = input.Texture.height; int y = (int)(h * input.UV.y);
if (Config.BilinearSample) int tidx = y*w + x;
{
textureColor = input.Texture.GetPixelBilinear(input.UV.x, input.UV.y); URColor24 c = input.TextureData[tidx];
} Color textureColor = (URColor24)c;
else // if (input.Texture != null)
{ // {
textureColor = input.Texture.GetPixel((int)(w * input.UV.x), (int)(h * input.UV.y)); // int w = input.Texture.width;
} // int h = input.Texture.height;
// if (Config.BilinearSample)
// {
// textureColor = input.Texture.GetPixelBilinear(input.UV.x, input.UV.y);
// }
// else
// {
// textureColor = input.Texture.GetPixel((int)(w * input.UV.x), (int)(h * input.UV.y));
// }
} // }
Color ambient = Uniforms.AmbientColor; Color ambient = Uniforms.AmbientColor;
......
...@@ -98,6 +98,13 @@ namespace URasterizer ...@@ -98,6 +98,13 @@ namespace URasterizer
} }
} }
void OnDestroy()
{
_cpuRasterizer.Release();
_jobRasterizer.Release();
_gpuRasterizer.Release();
}
void Render() void Render()
{ {
......
using UnityEngine;
using System;
namespace URasterizer
{
public class URUtils
{
static Vector4[] s_tmp8Vector4s = new Vector4[8];
public static void FillArray<T>(T[] arr, T value)
{
int i = 0;
if(arr.Length > 16)
{
do
{
arr[i++] = value;
} while (i < arr.Length);
while( i + 16 < arr.Length)
{
Array.Copy(arr, 0, arr, i, 16);
i += 16;
}
}
while (i < arr.Length)
{
arr[i++] = value;
}
}
//在ClipSpace中,判断OBB顶点是否在视锥外部。输入v为clip space下OBB的8个顶点
//该函数使用的是保守视锥剔除算法,对于每个裁剪面都检查OBB的所有顶点是否在它外面,如果都在则剔除
//该算法是保守的,不会错误剔除掉不该剔除的OBB,但是可能有一些特殊位置的OBB剔除不掉,
//比如当OBB比较大且在视锥外,但是同时和左右近3个面相交,这样这3个面就无法成功判断剔除。
//这种情况一般是离镜头很近的大的墙体,可能会剔除不掉,造成性能问题。
//可参考:https://www.iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
public static bool CheckVerticesOutFrustumClipSpace(Vector4[] v)
{
//left
int cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].x < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//right
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].x > w){
++cnt;
}
if(cnt==8){
return true;
}
}
//bottom
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].y < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//top
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].y > w){
++cnt;
}
if(cnt==8){
return true;
}
}
//near
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].z < -w){
++cnt;
}
if(cnt==8){
return true;
}
}
//far
cnt = 0;
for(int i=0; i < 8; ++i){
var w = v[i].w >=0 ? v[i].w : -v[i].w;
if(v[i].z > w){
++cnt;
}
if(cnt==8){
return true;
}
}
return false;
}
public static bool FrustumCulling(Bounds localAABB, Matrix4x4 mvp)
{
var v = s_tmp8Vector4s;
var min = localAABB.min; min.z = -min.z;
var max = localAABB.max; max.z = -max.z;
v[0] = mvp * new Vector4(min.x, min.y, min.z, 1.0f);
v[1] = mvp * new Vector4(min.x, min.y, max.z, 1.0f);
v[2] = mvp * new Vector4(min.x, max.y, min.z, 1.0f);
v[3] = mvp * new Vector4(min.x, max.y, max.z, 1.0f);
v[4] = mvp * new Vector4(max.x, min.y, min.z, 1.0f);
v[5] = mvp * new Vector4(max.x, min.y, max.z, 1.0f);
v[6] = mvp * new Vector4(max.x, max.y, min.z, 1.0f);
v[7] = mvp * new Vector4(max.x, max.y, max.z, 1.0f);
return CheckVerticesOutFrustumClipSpace(v);
}
}
}
fileFormatVersion: 2 fileFormatVersion: 2
guid: abf6119db9e645441ac288e1d50d430e guid: 936e498eee168924da968bf1f5118254
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
...@@ -103,6 +103,12 @@ namespace URasterizer ...@@ -103,6 +103,12 @@ namespace URasterizer
ambientColorId = Shader.PropertyToID("ambientColor"); ambientColorId = Shader.PropertyToID("ambientColor");
meshTextureId = Shader.PropertyToID("meshTexture"); meshTextureId = Shader.PropertyToID("meshTexture");
} }
public void Release()
{
_colorTexture = null;
_depthTexture = null;
}
public float Aspect public float Aspect
......
...@@ -13,6 +13,8 @@ namespace URasterizer ...@@ -13,6 +13,8 @@ namespace URasterizer
Texture ColorTexture { get; } Texture ColorTexture { get; }
void UpdateFrame(); void UpdateFrame();
void Release();
} }
} }
\ No newline at end of file
...@@ -4,38 +4,43 @@ using Unity.Collections; ...@@ -4,38 +4,43 @@ using Unity.Collections;
namespace URasterizer namespace URasterizer
{ {
public struct RenderInputData
{
public Vector3 vertex;
public Vector3 normal;
public RenderInputData(Vector3 v, Vector3 n){
vertex = v;
normal = n;
}
}
public class JobRenderObjectData : IRenderObjectData public class JobRenderObjectData : IRenderObjectData
{ {
[ReadOnly] public NativeArray<Vector3> positionData;
public NativeArray<RenderInputData> inputData; public NativeArray<Vector3> normalData;
public NativeArray<Vector2> uvData;
public NativeArray<Vector3Int> trianglesData;
public JobRenderObjectData(Mesh mesh) public JobRenderObjectData(Mesh mesh)
{ {
inputData = new NativeArray<RenderInputData>(mesh.vertexCount, Allocator.Persistent); positionData = new NativeArray<Vector3>(mesh.vertexCount, Allocator.Persistent);
positionData.CopyFrom(mesh.vertices);
var meshVertices = mesh.vertices;
var meshNormals = mesh.normals; normalData = new NativeArray<Vector3>(mesh.vertexCount, Allocator.Persistent);
normalData.CopyFrom(mesh.normals);
for(int i=0; i<mesh.vertexCount; ++i){
inputData[i] = new RenderInputData(meshVertices[i], meshNormals[i]); uvData = new NativeArray<Vector2>(mesh.vertexCount, Allocator.Persistent);
} uvData.CopyFrom(mesh.uv);
//初始化三角形数组,每个三角形包含3个索引值
//注意这儿对调了v0和v1的索引,因为原来的 0,1,2是顺时针的,对调后是 1,0,2是逆时针的
//Unity Quard模型的两个三角形索引分别是 0,3,1,3,0,2 转换后为 3,0,1,0,3,2
var mesh_triangles = mesh.triangles;
int triCnt = mesh_triangles.Length/3;
trianglesData = new NativeArray<Vector3Int>(triCnt, Allocator.Persistent);
for(int i=0; i < triCnt; ++i){
int j = i * 3;
trianglesData[i] = new Vector3Int(mesh_triangles[j+1], mesh_triangles[j], mesh_triangles[j+2]);
}
} }
public void Release() public void Release()
{ {
inputData.Dispose(); positionData.Dispose();
normalData.Dispose();
uvData.Dispose();
trianglesData.Dispose();
} }
} }
......
using System;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
namespace URasterizer
{
public struct TriangleJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<Vector3Int> trianglesData;
[ReadOnly]
public NativeArray<Vector2> uvData;
[ReadOnly]
public NativeArray<VSOutBuf> vsOutput;
[NativeDisableParallelForRestriction]
public NativeArray<Color> frameBuffer;
[NativeDisableParallelForRestriction]
public NativeArray<float> depthBuffer;
public int screenWidth;
public int screenHeight;
[ReadOnly]
public NativeArray<URColor24> TextureData;
public int TextureWidth;
public int TextureHeight;
public ShaderType fsType;
public void Execute(int index)
{
var _tmpVector4s = new Vector4[3];
Vector3Int triangle = trianglesData[index];
int idx0 = triangle.x;
int idx1 = triangle.y;
int idx2 = triangle.z;
Vector4[] v = _tmpVector4s;
v[0] = vsOutput[idx0].clipPos;
v[1] = vsOutput[idx1].clipPos;
v[2] = vsOutput[idx2].clipPos;
// ------ Clipping -------
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
{
Vector3 v0 = new Vector3(v[0].x, v[0].y, v[0].z);
Vector3 v1 = new Vector3(v[1].x, v[1].y, v[1].z);
Vector3 v2 = new Vector3(v[2].x, v[2].y, v[2].z);
Vector3 e01 = v1 - v0;
Vector3 e02 = v2 - v0;
Vector3 cross = Vector3.Cross(e01, e02);
if (cross.z < 0)
{
return;
}
}
// ------- Viewport Transform ----------
//NDC to screen space
for (int k = 0; k < 3; k++)
{
var vec = v[k];
vec.x = 0.5f * screenWidth * (vec.x + 1.0f);
vec.y = 0.5f * screenHeight * (vec.y + 1.0f);
vec.z = vec.z * 0.5f + 0.5f;
v[k] = vec;
}
Triangle t = new Triangle();
t.Vertex0.Position = v[0];
t.Vertex1.Position = v[1];
t.Vertex2.Position = v[2];
//set obj normal
t.Vertex0.Normal = vsOutput[idx0].objectNormal;
t.Vertex1.Normal = vsOutput[idx1].objectNormal;
t.Vertex2.Normal = vsOutput[idx2].objectNormal;
t.Vertex0.Texcoord = uvData[idx0];
t.Vertex1.Texcoord = uvData[idx1];
t.Vertex2.Texcoord = uvData[idx2];
t.Vertex0.Color = Color.white;
t.Vertex1.Color = Color.white;
t.Vertex2.Color = Color.white;
//set world space pos & normal
t.Vertex0.WorldPos = vsOutput[idx0].worldPos;
t.Vertex1.WorldPos = vsOutput[idx1].worldPos;
t.Vertex2.WorldPos = vsOutput[idx2].worldPos;
t.Vertex0.WorldNormal = vsOutput[idx0].worldNormal;
t.Vertex1.WorldNormal = vsOutput[idx1].worldNormal;
t.Vertex2.WorldNormal = vsOutput[idx2].worldNormal;
RasterizeTriangle(t, v);
}
bool Clipped(Vector4[] v)
{
//分别检查视锥体的六个面,如果三角形所有三个顶点都在某个面之外,则该三角形在视锥外,剔除
//由于NDC中总是满足-1<=Zndc<=1, 而当 w < 0 时,-w >= Zclip = Zndc*w >= w。所以此时clip space的坐标范围是[w,-w], 为了比较时更明确,将w取正
var v0 = v[0];
var w0 = v0.w >=0 ? v0.w : -v0.w;
var v1 = v[1];
var w1 = v1.w >=0 ? v1.w : -v1.w;
var v2 = v[2];
var w2 = v2.w >=0 ? v2.w : -v2.w;
//left
if(v0.x < -w0 && v1.x < -w1 && v2.x < -w2){
return true;
}
//right
if(v0.x > w0 && v1.x > w1 && v2.x > w2){
return true;
}
//bottom
if(v0.y < -w0 && v1.y < -w1 && v2.y < -w2){
return true;
}
//top
if(v0.y > w0 && v1.y > w1 && v2.y > w2){
return true;
}
//near
if(v0.z < -w0 && v1.z < -w1 && v2.z < -w2){
return true;
}
//far
if(v0.z > w0 && v1.z > w1 && v2.z > w2){
return true;
}
return false;
}
Vector3 ComputeBarycentric2D(float x, float y, Triangle t, Vector4[] _tmpVector4s)
{
ProfileManager.BeginSample("JobRasterizer.ComputeBarycentric2D");
var v = _tmpVector4s;
v[0] = t.Vertex0.Position;
v[1] = t.Vertex1.Position;
v[2] = t.Vertex2.Position;
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);
ProfileManager.EndSample();
return new Vector3(c1, c2, c3);
}
public int GetIndex(int x, int y)
{
return y * screenWidth + x;
}
void RasterizeTriangle(Triangle t, Vector4[] _tmpVector4s)
{
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 > screenWidth ? screenWidth : maxPX;
int minPY = Mathf.FloorToInt(minY);
minPY = minPY < 0 ? 0 : minPY;
int maxPY = Mathf.CeilToInt(maxY);
maxPY = maxPY > screenHeight ? screenHeight : maxPY;
// 遍历当前三角形包围中的所有像素,判断当前像素是否在三角形中
// 对于在三角形中的像素,使用重心坐标插值得到深度值,并使用z buffer进行深度测试和写入
for(int y = minPY; y < maxPY; ++y)
{
for(int x = minPX; x < maxPX; ++x)
{
//计算重心坐标
var c = ComputeBarycentric2D(x, y, t, 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,因此大值通过测试)
int index = GetIndex(x, y);
if(zp >= depthBuffer[index])
{
depthBuffer[index] = zp;
//透视校正插值
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;
FragmentShaderInputData input = new FragmentShaderInputData();
input.Color = color_p;
input.UV = uv_p;
input.TextureData = TextureData;
input.TextureWidth = TextureWidth;
input.TextureHeight = TextureHeight;
input.LocalNormal = normal_p;
input.WorldPos = worldPos_p;
input.WorldNormal = worldNormal_p;
switch(fsType){
case ShaderType.BlinnPhong:
frameBuffer[index] = ShaderContext.FSBlinnPhong(input);
break;
case ShaderType.NormalVisual:
frameBuffer[index] = ShaderContext.FSNormalVisual(input);
break;
case ShaderType.VertexColor:
frameBuffer[index] = ShaderContext.FSVertexColor(input);
break;
}
}
}
}
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 353946cbdfe58c84b9fd5922aab7ce68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
...@@ -8,7 +8,9 @@ namespace URasterizer ...@@ -8,7 +8,9 @@ namespace URasterizer
public struct VertexShadingJob : IJobParallelFor public struct VertexShadingJob : IJobParallelFor
{ {
[ReadOnly] [ReadOnly]
public NativeArray<RenderInputData> inputData; public NativeArray<Vector3> positionData;
[ReadOnly]
public NativeArray<Vector3> normalData;
public Matrix4x4 mvpMat; public Matrix4x4 mvpMat;
public Matrix4x4 modelMat; public Matrix4x4 modelMat;
...@@ -17,10 +19,9 @@ namespace URasterizer ...@@ -17,10 +19,9 @@ namespace URasterizer
public NativeArray<VSOutBuf> result; public NativeArray<VSOutBuf> result;
public void Execute(int index) public void Execute(int index)
{ {
RenderInputData input = inputData[index]; var vert = positionData[index];
var vert = input.vertex; var normal = normalData[index];
var normal = input.normal;
var output = result[index]; var output = result[index];
var objVert = new Vector4(vert.x, vert.y, -vert.z, 1); var objVert = new Vector4(vert.x, vert.y, -vert.z, 1);
......
fileFormatVersion: 2
guid: 0744978f99018c24cad9ab17221bacb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
...@@ -12,9 +12,9 @@ MonoBehaviour: ...@@ -12,9 +12,9 @@ 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, g: 0, b: 0, a: 0} ClearColor: {r: 0.4716981, g: 0.4716981, b: 0.4716981, a: 0.72156864}
AmbientColor: {r: 0.0754717, g: 0.0754717, b: 0.0754717, a: 1} AmbientColor: {r: 0.0754717, g: 0.0754717, b: 0.0754717, a: 1}
RasterizerType: 1 RasterizerType: 0
UseUnityNativeRendering: 0 UseUnityNativeRendering: 0
WireframeMode: 0 WireframeMode: 0
FrustumCulling: 1 FrustumCulling: 1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册