Skip to content

Commit cd4ce7e

Browse files
增加聚光灯光源~,增加面剔除功能~
1 parent 098d526 commit cd4ce7e

13 files changed

+2645
-3669
lines changed

CullingFaceMode.cs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace SortRenderWithCSharp {
8+
public enum CullingFaceMode {
9+
// 剔除背面
10+
Back,
11+
// 剔除正面
12+
Front,
13+
// 剔除所有面
14+
All
15+
}
16+
}

Lights/SpotLight.cs

+10-14
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,29 @@ public class SpotLight : Light {
2929

3030
public SpotLight(float outerAngle,float innerAngle, Vector3 spotDir,Color01 lightColor,Vector3 position) {
3131
this.outerAngle = outerAngle;
32-
this.cosPhi = (float)Math.Cos(outerAngle);
32+
this.cosPhi = (float)Math.Cos(outerAngle * MathF.Deg2Rad);
3333
this.spotDir = spotDir;
3434

35+
36+
3537
this.innerAngle = innerAngle;
36-
this.cosInnerAngle = (float)Math.Cos(innerAngle);
38+
this.cosInnerAngle = (float)Math.Cos(innerAngle * MathF.Deg2Rad);
3739

3840
this.lightColor = lightColor;
3941

4042
this.position = position;
4143
}
4244

4345
public override float GetAtten(Vector3 targetPosition) {
44-
//// LightDir和SpotDir的夹角(cos),也就是当前片元距离
45-
//float theta = Vector3.Dot(GetDirection(targetPosition),spotDir);
46-
//// Epsilon是内外圆锥的余弦差值
47-
//float epsilon = cosInnerAngle - cosPhi;
48-
//// 聚光灯强度
49-
//float intensity = MathF.Clamp01((theta-cosPhi)/epsilon);
50-
51-
//return intensity;
5246

5347
// θ,片元指向光源的方向与聚光灯朝向的夹角(cos)
5448
float cosTheta = Vector3.Dot(-GetDirection(targetPosition).normlize,spotDir.normlize);
55-
if (cosTheta > cosPhi) {
56-
return 1;
57-
} else
58-
return 0;
49+
// Epsilon是内外圆锥的余弦差值
50+
float epsilon = cosInnerAngle - cosPhi;
51+
// 聚光灯强度
52+
float intensity = MathF.Clamp01((cosTheta - cosPhi) / epsilon);
53+
54+
return intensity;
5955
}
6056
}
6157
}

MathF.cs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
namespace SortRenderWithCSharp {
99
class MathF {
1010

11+
public static float Deg2Rad = (float)(Math.PI/180f);
12+
1113
/// <summary>
1214
/// 返回x的小数部分
1315
/// </summary>

Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Program {
1010
/// 应用程序的主入口点。
1111
/// </summary>
1212
[STAThread]
13-
static void Main() {
13+
static void Main() {
1414
Application.EnableVisualStyles();
1515
Application.SetCompatibleTextRenderingDefault(false);
1616
Application.Run(new SoftRenderForm());

SoftRenderForm.cs

+79-22
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public class SoftRenderForm : Form {
4949
PointLight pointLight;
5050
// 聚光灯
5151
SpotLight spotLight;
52-
52+
53+
// 是否开启面剔除功能
54+
bool cullingFaceOn = false;
55+
CullingFaceMode cullingFaceMode = CullingFaceMode.Back;
5356

5457
// 屏幕宽高度(同时也作分辨率使用)
5558
private int screenHeight = 500, screenWidth = 500;
@@ -83,9 +86,9 @@ public SoftRenderForm() {
8386
// 初始化所有光源
8487
//directionalLight = new DirectionalLight(MainLightDirection, Color01.White);
8588
//lights.Add(directionalLight);
86-
//pointLight = new PointLight(Vector3.Zero,7,new Color01(0,0,1f,1f));
89+
//pointLight = new PointLight(Vector3.Zero, 7, new Color01(0, 0, 1f, 1f));
8790
//lights.Add(pointLight);
88-
spotLight = new SpotLight(45,7f,new Vector3(0,0,1),new Color01(1,1,1,1),new Vector3(0,0,-3));
91+
spotLight = new SpotLight(15f, 7f, new Vector3(0, 0, 1), new Color01(1, 1, 1, 1), new Vector3(0, 0, -3));
8992
lights.Add(spotLight);
9093

9194
// 开启深度测试
@@ -111,7 +114,7 @@ public SoftRenderForm() {
111114

112115
// 读取OBJ文件
113116
SpaceShip = OBJLoader.LoadOBJ("../../enemry_spaceship.obj");
114-
//cube = OBJLoader.LoadOBJ("../../cube.obj");
117+
//cube = OBJLoader.LoadOBJ("../../cube2.obj");
115118
cube = new Cube();
116119
sphere = OBJLoader.LoadOBJ("../../sphere.obj");
117120

@@ -134,7 +137,7 @@ protected override void OnMouseDown(MouseEventArgs e) {
134137

135138
private void UpdateInput() {
136139

137-
float cameraSpeed = 2.0f;
140+
float cameraSpeed = 5.0f;
138141
if (Input.Instance.isKeyDown) {
139142
switch (Input.Instance.keyCode) {
140143
case Keys.Left:
@@ -613,11 +616,27 @@ public Vertex ScreenMapping(Vertex v) {
613616
/// <param name="v1"></param>
614617
/// <param name="v2"></param>
615618
/// <param name="v3"></param>
616-
public void DrawPrimitive(Vertex v1,Vertex v2,Vertex v3,Matrix4x4 mvp) {
619+
public void DrawPrimitive(Vertex v1,Vertex v2,Vertex v3,Matrix4x4 mMatrix,Matrix4x4 vMatrix,Matrix4x4 pMatrix) {
617620
// 将各顶点作为列矩阵进行MVP变换
618-
v1.pos = mvp * v1.modelSpacePos;
619-
v2.pos = mvp * v2.modelSpacePos;
620-
v3.pos = mvp * v3.modelSpacePos;
621+
//v1.pos = mvp * v1.modelSpacePos;
622+
//v2.pos = mvp * v2.modelSpacePos;
623+
//v3.pos = mvp * v3.modelSpacePos;
624+
625+
// 先将顶点变换到观察空间下
626+
Matrix4x4 mvMatrix = vMatrix * mMatrix;
627+
v1.pos = mvMatrix * v1.modelSpacePos;
628+
v2.pos = mvMatrix * v2.modelSpacePos;
629+
v3.pos = mvMatrix * v3.modelSpacePos;
630+
631+
// 判断是否通过面剔除
632+
if (!FaceCulling(v1,v2,v3) && cullingFaceOn) {
633+
return;
634+
}
635+
636+
// 将所有顶点变换到裁剪空间下
637+
v1.pos = pMatrix * v1.pos;
638+
v2.pos = pMatrix * v2.pos;
639+
v3.pos = pMatrix * v3.pos;
621640

622641
// 判断有顶点是否应该被裁剪
623642
if (CVVCutting(v1.pos) ||
@@ -644,7 +663,7 @@ public void DrawPrimitive(Vertex v1,Vertex v2,Vertex v3,Matrix4x4 mvp) {
644663
/// <param name="triangle"></param>
645664
/// <param name="mvp"></param>
646665
/// <param name="drawMode">默认为连续三角形绘制</param>
647-
public void DrawElement(Mesh mesh,Matrix4x4 mvp,SoftRenderDrawMode drawMode= SoftRenderDrawMode.Triangles) {
666+
public void DrawElement(Mesh mesh, Matrix4x4 mMatrix, Matrix4x4 vMatrix, Matrix4x4 pMatrix, SoftRenderDrawMode drawMode= SoftRenderDrawMode.Triangles) {
648667
int[] triangle = mesh.triangles;
649668
Vertex[] vertices = mesh.vertices;
650669
if (triangle.Length % 3 != 0) return;
@@ -656,16 +675,16 @@ public void DrawElement(Mesh mesh,Matrix4x4 mvp,SoftRenderDrawMode drawMode= Sof
656675
Vertex v2 = vertices[triangle[i + 1]];
657676
Vertex v3 = vertices[triangle[i + 2]];
658677

659-
DrawPrimitive(v1, v2, v3, mvp);
678+
DrawPrimitive(v1, v2, v3, mMatrix,vMatrix,pMatrix);
660679
}
661680
break;
662681
case SoftRenderDrawMode.Triangles_FUN:
663682
Vertex v_init = vertices[triangle[0]];
664-
for (int i = 1; i < triangle.Length; i+=2) {
665-
Vertex v2 = vertices[triangle[i + 1]];
666-
Vertex v3 = vertices[triangle[i + 2]];
683+
for (int i = 1; i+1 < triangle.Length; i+=2) {
684+
Vertex v2 = vertices[triangle[i]];
685+
Vertex v3 = vertices[triangle[i + 1]];
667686

668-
DrawPrimitive(v_init, v2, v3, mvp);
687+
DrawPrimitive(v_init, v2, v3, mMatrix, vMatrix, pMatrix);
669688
}
670689
break;
671690
case SoftRenderDrawMode.TRIANGLE_STRIP:
@@ -674,14 +693,14 @@ public void DrawElement(Mesh mesh,Matrix4x4 mvp,SoftRenderDrawMode drawMode= Sof
674693
Vertex vsecond = vertices[triangle[1]];
675694
Vertex vthird = vertices[triangle[2]];
676695

677-
DrawPrimitive(vfirset,vsecond,vthird,mvp);
696+
DrawPrimitive(vfirset,vsecond,vthird, mMatrix, vMatrix, pMatrix);
678697

679698
for (int i=3;i<triangle.Length;i++) {
680699
Vertex v1 = vertices[triangle[i - 2]];
681700
Vertex v2 = vertices[triangle[i - 1]];
682701
Vertex v3 = vertices[triangle[i]];
683702

684-
DrawPrimitive(v1,v2,v3,mvp);
703+
DrawPrimitive(v1,v2,v3, mMatrix, vMatrix, pMatrix);
685704
}
686705

687706
break;
@@ -720,6 +739,44 @@ public bool ZTest(int px,int py,float pz) {
720739

721740
#endregion
722741

742+
743+
#region 面剔除测试
744+
745+
public bool FaceCulling(Vertex v1,Vertex v2,Vertex v3) {
746+
// v2指向v1的向量
747+
Vector3 p1 = v2.pos - v1.pos;
748+
// v3指向v1的向量
749+
Vector3 p2 = v3.pos - v2.pos;
750+
751+
// 获得p1和p2的叉积
752+
Vector3 normal = Vector3.Cross(p1,p2);
753+
754+
// 获得视空间内从顶点望向观察方向的向量
755+
Vector3 viewDir = -v1.pos + Vector3.Zero;
756+
757+
// 如果该叉积结果和观察方向一致,那么说明该面面朝摄像机,即为逆时针,
758+
// 否则说明该面背朝摄像机,为顺时针
759+
switch (cullingFaceMode) {
760+
case CullingFaceMode.Back:
761+
if (Vector3.Dot(normal, viewDir) > 0) {
762+
return true;
763+
}
764+
break;
765+
case CullingFaceMode.Front:
766+
if (Vector3.Dot(normal, viewDir) < 0) {
767+
return true;
768+
}
769+
break;
770+
case CullingFaceMode.All:
771+
return true;
772+
}
773+
774+
775+
return false;
776+
}
777+
778+
#endregion
779+
723780
#region 绘制更多图元
724781
Mesh SpaceShip;
725782
Mesh cube;
@@ -734,7 +791,7 @@ public void DrawMesh(Mesh mesh,Vector3 position,Vector3 scale,Vector3 rotation,S
734791
Matrix4x4 projectionMatrix = camera.GetProjectionMatrix();
735792

736793
// 构建MVP矩阵
737-
Matrix4x4 MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
794+
//Matrix4x4 MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
738795

739796
// 给每个顶点引用一份MVP矩阵
740797
//foreach (int i in mesh.triangles) {
@@ -748,7 +805,7 @@ public void DrawMesh(Mesh mesh,Vector3 position,Vector3 scale,Vector3 rotation,S
748805
mesh.pMatrix = projectionMatrix;
749806

750807

751-
DrawElement(mesh, MVPMatrix,softRenderDrawMode);
808+
DrawElement(mesh, modelMatrix,viewMatrix,projectionMatrix,softRenderDrawMode);
752809
}
753810

754811
/// <summary>
@@ -761,7 +818,7 @@ public void DrawMesh(Mesh mesh,SoftRenderDrawMode drawMode=SoftRenderDrawMode.Tr
761818
// 坐标/旋转与缩放
762819
angel = (angel + 1) % 720;
763820
Vector3 rotation = new Vector3(angel, angel, angel);
764-
Vector3 scale = new Vector3(1, 1, 1)*3;
821+
Vector3 scale = new Vector3(1, 1, 1)*2;
765822
Vector3 worldPosition = new Vector3(0, 0, 0);
766823

767824
// 构建M矩阵
@@ -772,7 +829,7 @@ public void DrawMesh(Mesh mesh,SoftRenderDrawMode drawMode=SoftRenderDrawMode.Tr
772829
Matrix4x4 projectionMatrix = camera.GetProjectionMatrix();
773830

774831
// 构建MVP矩阵
775-
Matrix4x4 MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
832+
//Matrix4x4 MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
776833

777834
//// 给每个顶点引用一份MVP矩阵
778835
//foreach (int i in mesh.triangles) {
@@ -786,7 +843,7 @@ public void DrawMesh(Mesh mesh,SoftRenderDrawMode drawMode=SoftRenderDrawMode.Tr
786843
mesh.pMatrix = projectionMatrix;
787844

788845

789-
DrawElement(mesh, MVPMatrix,drawMode);
846+
DrawElement(mesh, modelMatrix, viewMatrix, projectionMatrix, drawMode);
790847
}
791848

792849
#region 光照模型

SortRenderWithCSharp.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Compile Include="Camera.cs" />
5050
<Compile Include="Color01.cs" />
5151
<Compile Include="Cube.cs" />
52+
<Compile Include="CullingFaceMode.cs" />
5253
<Compile Include="Input.cs" />
5354
<Compile Include="Lights\DirectionalLight.cs" />
5455
<Compile Include="Lights\Light.cs" />

Vertex.cs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public Vertex(Vector3 pos,Color01 c,float u,float v) {
4040
public static Vertex LerpVertexData(Vertex left,Vertex right,float t) {
4141
Vertex result = new Vertex();
4242

43+
result.modelSpacePos = Vector3.LerpVector3(left.modelSpacePos,right.modelSpacePos,t);
4344
// 对z值进行插值
4445
result.pos.Z = MathF.LerpFloat(left.pos.Z,right.pos.Z,t);
4546
// 对颜色属性进行插值

bin/Debug/SortRenderWithCSharp.exe

512 Bytes
Binary file not shown.

bin/Debug/SortRenderWithCSharp.pdb

2 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eed859456c05b96fd275a902cd52a5f43b1148d6
1+
3d85c90dd001a28c89942b770693745776729de8

obj/Debug/SortRenderWithCSharp.exe

512 Bytes
Binary file not shown.

obj/Debug/SortRenderWithCSharp.pdb

2 KB
Binary file not shown.

0 commit comments

Comments
 (0)