【发布时间】:2022-05-21 04:32:20
【问题描述】:
我正在使用 Unity 5.5 和 WebGL 构建一个多边形工具,我想用它来裁剪图像中的选择。该项目使用着色器文件来定义构成多边形的点和区域。您可以在下面看到着色器的代码,以及代码文件。
我目前遇到的问题是项目在编辑器中运行良好,但 WebGL 构建在浏览器中显示为粉红色。多边形着色器不会渲染,如果我在文件中设置了一个后备着色器,它会加载那个。我在网上查了这个问题,发现并尝试了以下方法:
- 重新导入所有资产,因为可能缺少某些内容。检查层次结构中的所有游戏对象是否有损坏的引用。
- 确保着色器位于项目图形设置的“始终包含的着色器”列表中。
- 潜在的内存泄漏?我将分配给项目的 MB 数增加到 1024,通过压缩纹理来降低纹理大小,并在编辑器中运行 Profiler。 Profiler 记录的最大总使用量约为 220MB。
- 切换质量设置 - 我发现如果没有启用抗锯齿,着色器将无法工作。
- 显卡不支持着色器?网上的人在 OS X(我也在使用)上报告了类似的问题,但他们没有更新他们的查询。
我应该注意到项目中没有错误或警告。我不确定问题出在哪里,并且非常感谢对此问题的任何看法。请让我知道是否有任何我可以提供的进一步信息可以简化流程!提前感谢您的帮助:)
Polygon.cs 文件:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
public class Polygon : MonoBehaviour {
public Material mat; //Binding materials; Polygon shader applied to it.
Vector3[] worldPos; //Store 3D coordinates
Vector4[] screenPos; //Store to draw the polygon vertices in screen coordinates
int maxPointNum = 6; //Total number of polygon vertices
int currentpointNum = 0; //Current number of points placed
int pointNum2Shader = 0; //Transfer number of vertices to shader
bool InSelection = true; //Vertex gets is in the process
void Start() {
worldPos = new Vector3[maxPointNum];
screenPos = new Vector4[maxPointNum];
}
void Update() {
mat.SetVectorArray("Value", screenPos); //Pass the vertex position information to the screen shader.
mat.SetInt("PointNum", pointNum2Shader); //Transfer number of vertices to shader
//Cameras fired a ray to get to select a 3D location
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100)) {
Debug.DrawLine(ray.origin, hit.point);
}
//Use mouse clicks to obtain location information
if (Input.GetMouseButtonDown(0) && InSelection) {
if (currentpointNum < maxPointNum) {
currentpointNum++;
pointNum2Shader++;
worldPos[currentpointNum - 1] = hit.point;
//Vector3 v3 = Camera.main.ScreenToWorldPoint (worldPos [currentpointNum-1]);
Vector3 v3 = Camera.main.WorldToScreenPoint(worldPos[currentpointNum - 1]);
screenPos[currentpointNum - 1] = new Vector4(v3.x, v3.y, v3.z, 0);
}
else {
InSelection = false;
}
}
//Updated in real time screens of 3D point selected location
for (int i = 0; i < maxPointNum; i++) {
Vector3 v3 = Camera.main.WorldToScreenPoint(worldPos[i]);
screenPos[i] = new Vector4(v3.x, v3.y, v3.z, 0);
}
//Detect if 3d point is behind the camera, if you stop drawing
for (int i = 0; i < currentpointNum; i++) {
if (Vector3.Dot(worldPos[i] - Camera.main.transform.position, Camera.main.transform.forward) <= 0) {
pointNum2Shader = 0;
break;
}
pointNum2Shader = currentpointNum;
}
}
//Grab the current rendering of image processing
void OnRenderImage(RenderTexture src, RenderTexture dest) {
Graphics.Blit(src, dest, mat);
}
void OnGUI () {
float btnWidth = 100;
float btnHeight = 50;
float y = 150;
if (GUI.Button(new Rect(100, y, btnWidth, btnHeight), "Crop")) {
Vector2[] vertices2D = new Vector2[maxPointNum];
for (int i = 0; i < currentpointNum; i++) {
vertices2D[i].x = worldPos[i].x;
vertices2D[i].y = worldPos[i].y;
}
// Use the triangulator to get indices for creating triangles
Triangulator tr = new Triangulator(vertices2D);
int[] indices = tr.Triangulate();
GameObject plane = GameObject.Find("Plane");
MeshFilter filter = plane.GetComponent<MeshFilter>();
Vector3[] vertices = filter.mesh.vertices;
// Vector2[] texCoords = new Vector2[currentpointNum];
// for(int i = 0; i < currentpointNum; i++) {
// //There should be as many texture coordinates as vertices.
// //This example does not support textures, so fill with zeros
// texCoords[i] = new Vector2(vertices[i].x, vertices[i].y);
// }
// Create the mesh
Mesh msh = new Mesh();
msh.vertices = worldPos;
msh.triangles = indices;
msh.RecalculateNormals();
msh.RecalculateBounds();
filter.mesh = msh;
}
}
}
Polygon.shader 文件:
Shader "Unlit/polygon"
{
Properties
{
//Define basic properties can be set from inside the editor variable
//_MainTex ("Texture", 2D) = "white" {}
}
CGINCLUDE
// Upgrade NOTE: excluded shader from DX11 because it uses wrong array syntax (type[size] name)
#pragma exclude_renderers d3d11
//Incoming vertices function from the application data structure definitions
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
//Incoming segment from a vertex function from the data structure definitions
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
//Define mapping variables
sampler2D _MainTex;
// float4 _MainTex_ST;
//Define variables for communicating with the script
uniform float4 Value[6];
int PointNum = 0;
//Function that calculates the distance between two points
float Dis(float4 v1,float4 v2)
{
return sqrt(pow((v1.x-v2.x),2)+pow((v1.y-v2.y),2));
}
//Draw line segments
bool DrawLineSegment(float4 p1, float4 p2, float lineWidth,v2f i)
{
float4 center = float4((p1.x+p2.x)/2,(p1.y+p2.y)/2,0,0);
//Calculate distance between point and line
float d = abs((p2.y-p1.y)*i.vertex.x + (p1.x - p2.x)*i.vertex.y +p2.x*p1.y -p2.y*p1.x )/sqrt(pow(p2.y-p1.y,2) + pow(p1.x-p2.x,2));
//When less than or equal to half the line width, which belongs to the linear range, return true
float lineLength = sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2));
if(d<=lineWidth/2 && Dis(i.vertex,center)<lineLength/2)
{
return true;
}
return false;
}
//To draw a polygon, this limits the number of vertices is not more than 6. You can change.
bool pnpoly(int nvert, float4 vert[6], float testx, float testy)
{
int i, j;
bool c=false;
float vertx[6];
float verty[6];
for(int n=0;n<nvert;n++)
{
vertx[n] = vert[n].x;
verty[n] = vert[n].y;
}
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((verty[i]>testy) != (verty[j]>testy)) && (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
v2f vert (appdata v)
{
v2f o;
//Object vertices from model space to the camera cut space, or you can use the shorthand way:
//o.vertex = UnityObjectToClipPos(v.vertex);
o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
//2D UV coordinate transformation can also use shorthand methods
//o.uv = TRANSFORM_TEX(v.uv, _MainTex);
//o.uv = v.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//Draw a polygon vertex
for(int j=0;j<PointNum;j++)
{
if(Dis(i.vertex, Value[j])<3)
{
return fixed4(1,0,0,0.5);
}
}
//Draws the edges of the polygon
for(int k=0;k<PointNum;k++)
{
if(k==PointNum-1)
{
if(DrawLineSegment(Value[k],Value[0],2,i))
{
return fixed4(1,1,0,0.5);
}
}
else
{
if(DrawLineSegment(Value[k],Value[k+1],2,i))
{
return fixed4(1,1,0,0.5);
}
}
}
//Within the filled polygon
if(pnpoly(PointNum, Value,i.vertex.x ,i.vertex.y))
{
return fixed4(0,1,0,0.3);
}
return fixed4(0,0,0,0);
//fixed4 col = tex2D(_MainTex, i.uv);
//return col;
}
ENDCG
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
//Select Alpha blend mode
Blend SrcAlpha OneMinusSrcAlpha
//In the CGPROGRAM block of code to write your own processes
CGPROGRAM
//Defined segment function entry and vertex function respectively, Vert and Frag
#pragma vertex vert
#pragma fragment frag
//Contains the basic files, there are some macro definitions and basic functions
#include "UnityCG.cginc"
ENDCG
}
}
}
【问题讨论】:
-
由于没有答案/cmets,我会告诉你我会尝试什么:你可以将纹理源更改为来自互联网的随机图像(不要下载它,使用 url )?这有什么改变吗?可能需要一些调整:stackoverflow.com/questions/31765518/…
-
@MihaiOvidiuDrăgoi 您的意思是将多边形工具的着色器更改为纹理并使用图像纹理而不是着色器?恐怕这会失去所有多边形选择功能,因为它们已包含在着色器中。 ://
-
是的,但它也会排除所有其他可能的罪魁祸首。如果你以后很容易扭转它,我仍然会试一试。
-
@MihaiOvidiuDrăgoi 好的,是的,我一直在为着色器交换纹理,虽然我看不到我设置为纹理的图像(因为我正在替换功能),但屏幕不再是粉红色了,我可以看到其余的场景。所以我认为可以安全地假设它与着色器有关?
-
很高兴听到它对发现问题有所帮助,但我在着色器方面的经验几乎为零:(
标签: c# unity3d shader unity5 unity-webgl