一日一Shader·函数曲线绘制【SS_5】

12 篇文章 1 订阅

今天用UnityShader脚本来制作Shader。

先上最终效果图:

然后,还是直接上源码吧:

Shader "MyShader/SS_5"
{
	Properties
	{
		_X("X",float) = 0
		_Y("Y",float) = 0
		_Width("Width",float) = 1
		_Height("Height",float)=1
		_MainTex("Texture", 2D) = ""{}
		_Color("Color",Color) = (1,1,1,1)
		[Enum(SIN,0,COS,1,TAN,2,EXP,3,LOG,4,PLOGP,5,Custom,6)] _Type("CurveType", Float) = 0
	}
	SubShader
	{
		Tags{
			"RenderType" = "Transparent"
			}
		CGINCLUDE
		#include "UnityCG.cginc"		
		float _X;
		float _Y;
		float _Width;
		float _Height;
		Float _Type;
		fixed4 _Color;
		sampler2D _MainTex;

		struct appdata
		{
			float4 vertex : POSITION;
			float2 uv : TEXCOORD0;
			float3 normal : NORMAL;

		};
		struct v2f
		{
			float4 vertex : SV_POSITION;
			float2 uv : TEXCOORD0;
			float4 worldPos   : TEXCOORD1;
			float3 normal : TEXCOORD2;
		};
		v2f vert(appdata v)
		{
			v2f o;
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.uv = v.uv;
			o.worldPos = mul(unity_ObjectToWorld, v.vertex);
			o.normal = v.normal;
			return o;
		}
	
		fixed Fun0(fixed _x) {
			return sin(_x);
		}
		
		fixed Fun1(fixed _x) {
			return cos( _x ) ;
		}
	
		fixed Fun2(fixed _x) {
			return tan(_x);
		}	
		fixed Fun3(fixed _x) {
			return exp(_x);
		}		
		fixed Fun4(fixed _x) {
			return log(_x);
		}
		//熵公式
		fixed Fun5(fixed _x) {						
			return -_x*log(_x);
		}	
		fixed4 frag(v2f i) : SV_Target
		{ 
			fixed4 col = tex2D(_MainTex, i.uv);
			fixed x = _Time.y+_Width * (i.uv.x-0.5) - _X*0.01;//减0.5是为了居中;乘0.01是为了将坐标系单位放大100倍
			fixed y = Fun0(x);
			if (_Type == 1) {
				y = Fun1(x);
			}
			else if (_Type == 2) {
				y = Fun2(x);
			}
			else if (_Type == 3) {
				y = Fun3(x);
			}
			else if (_Type ==4) {
				y = Fun4(x);
			}
			else if (_Type ==5) {
				y = Fun5(x);
			}else if (_Type ==6) {
				y =abs(1+Fun0(3*x)*Fun1(10*x)*Fun0(3*x)/Fun1(2*x))-1;
			}
			fixed temp = i.uv.y;//因为要先绘制曲线,之后绘制坐标轴时会用到i.uv.y,所以先保存下来
			i.uv.y += -_Height*(y+_Y)*0.01;//乘0.01是为了将坐标系单位放大100倍
			fixed w = abs(1 / (100*(i.uv.y-0.5)));//减0.5是为了居中
			fixed4 wave=fixed4(w,w,w,1);
			if(wave.x+wave.y+wave.z>6)		//加这行是为了过滤掉,不过不加的话效果更好
			col +=wave*_Color;				//先绘制曲线
			
			w= abs(1 / (7000 * (temp - 0.5)));//除7000是为了让轴线更细
			col+= (fixed4(w, w, w, 1));//再绘制X坐标轴

			w = abs(1/(7000*(i.uv.x - 0.5)));
			col += (fixed4(w, w, w, 1));//再绘制Y坐标轴
			return col;
		}
		ENDCG
		Pass
		{
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
}

然后效果图的参数:

这个脚本还能扩展,修改波形的函数,或者直接通过cs脚本控制波形等等。

好的,以下是一个使用 Qt Shader 绘制二次贝塞尔曲线的代码示例: ```cpp #include <QGuiApplication> #include <QOpenGLShaderProgram> #include <QOpenGLFunctions> #include <QOpenGLVertexArrayObject> #include <QOpenGLBuffer> #include <QMatrix4x4> #include <QVector2D> class Window : public QWindow, protected QOpenGLFunctions { public: Window() : m_program(nullptr) , m_vao(nullptr) , m_vertexBuffer(nullptr) { } void initializeGL() { initializeOpenGLFunctions(); // Compile shaders m_program = new QOpenGLShaderProgram(this); m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertex.glsl"); m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fragment.glsl"); m_program->link(); // Create VAO m_vao = new QOpenGLVertexArrayObject(this); m_vao->create(); m_vao->bind(); // Create vertex buffer m_vertexBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); m_vertexBuffer->create(); m_vertexBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw); m_vertexBuffer->bind(); m_vertexBuffer->allocate(6 * sizeof(QVector2D)); // Define vertices for quadratic Bezier curve float x0 = 0.0f; float y0 = 0.0f; float x1 = 0.5f; float y1 = 1.0f; float x2 = 1.0f; float y2 = 0.0f; QVector2D vertices[] = { QVector2D(x0, y0), QVector2D(x1, y1), QVector2D(x2, y2), QVector2D(x0, y0), QVector2D(x1, y1), QVector2D(x2, y2) }; m_vertexBuffer->write(0, vertices, 6 * sizeof(QVector2D)); m_program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0); m_program->enableAttributeArray(0); // Release VAO and vertex buffer m_vao->release(); m_vertexBuffer->release(); } void paintGL() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); m_program->bind(); m_vao->bind(); // Set matrix uniform QMatrix4x4 matrix; matrix.setToIdentity(); m_program->setUniformValue("matrix", matrix); // Draw quadratic Bezier curve glDrawArrays(GL_TRIANGLES, 0, 6); m_vao->release(); m_program->release(); } private: QOpenGLShaderProgram* m_program; QOpenGLVertexArrayObject* m_vao; QOpenGLBuffer* m_vertexBuffer; }; int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); Window window; window.resize(640, 480); window.setTitle("Quadratic Bezier Curve"); window.show(); window.setSurfaceType(QWindow::OpenGLSurface); QSurfaceFormat format; format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); window.setFormat(format); window.create(); return app.exec(); } ``` 上面的代码使用了两个着色器,vertex.glsl 和 fragment.glsl,分别用于顶点着色和片段着色。这里只展示 vertex.glsl 的代码: ```glsl #version 330 core layout(location = 0) in vec2 position; uniform mat4 matrix; void main() { gl_Position = matrix * vec4(position, 0.0, 1.0); } ``` 这个着色器接受一个 2D 坐标作为输入,使用一个矩阵将其转换为裁剪空间坐标。在这个例子中,矩阵是一个单位矩阵,因此不会对顶点进行任何变换。 这个代码示例绘制的是一个简单的二次贝塞尔曲线,它的控制点为 (0.5, 1.0),起点和终点都为 (0.0, 0.0) 和 (1.0, 0.0)。这个曲线由两个三角形组成,因此顶点数为 6。 在 paintGL() 函数中,我们首先清除了颜色缓冲区,然后绑定着色器程序和 VAO。接着,我们将一个单位矩阵传递给着色器程序作为矩阵 uniform,这样顶点就不会被任何变换影响。最后,我们使用 glDrawArrays() 函数绘制二次贝塞尔曲线。 这个代码示例只是一个开始,你可以使用类似的方法绘制更复杂的二次或三次贝塞尔曲线,或者使用其他类型的曲线
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值