shader中绘制一个心

很早以前做cocos2dx的时候就看到官方着色器代码中已经有了一个现成的心型代码,故而网上也是有很多基于这个代码的,不过我觉得那个例子并不方便理解,所以就动手写一个容易理解的心型,核心数学公式是利用了笛卡尔的心型公式r=a(1-sinθ)。首先是最终结果示意图


下面是完整的着色器代码:

Shader "Custom/Heart" {
	Properties 
	{
		_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
     }
	CGINCLUDE
 	#include "UnityCG.cginc"
 	struct appdata 
 	{
		float4 vertex : POSITION;
		float2 texcoord : TEXCOORD0;
	};
	struct v2f {
		float4 vertex : SV_POSITION;
		half2 texcoord : TEXCOORD0;
	};
	sampler2D _MainTex; 
	float4 _MainTex_ST;
	
	v2f vert (appdata v)
	{
		v2f o;
    	o.vertex = mul (UNITY_MATRIX_MVP, v.vertex);   
    	o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); 
    	return o;
	}
	fixed4 frag (v2f i) : SV_Target
	{
		//画心
		float _x = i.texcoord.x - 0.5;
		float _y = i.texcoord.y - 0.5;
		float len = sqrt(_x*_x + _y*_y);
		float atan_x_y = atan(_y/_x);
		//距离远点
		float r = 0.2*(1 - _y/len); <span style="white-space:pre">	</span>这里就是笛卡尔的心型公式,r是得到的距离,当当前片段小于该距离说明该片段处于心内部,这里没有使用其他花哨的技巧就一个if-else,是为了方便理解
		if (len < r)
		{
			return float4(1, 0, 0, 1);
		}
		else
		{
			return float4(1, 1, 0, 1);
		}
		
	}
 	ENDCG
 	
	SubShader {
		Tags { "Queue" = "Transparent" }
		Pass 
		{
			Cull Off
			Blend SrcAlpha OneMinusSrcAlpha 
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
    FallBack "Diffuse"
}

而关于笛卡尔心型的理解,网上已经有很好解释,这里就给一个链接吧:http://www.360doc.com/content/07/0203/21/4213_354845.shtml

好的,以下是一个使用 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
发出的红包

打赏作者

梁工123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值