利用shader绘制一个带经纬度的球体

引子: 这是曾经的一道webgl面试题。

出处

利用shader绘制一个带经纬度的球体

最终效果:
在这里插入图片描述

代码

1、创建几何球体

这部分很基础,很快带过然后进入shader
App.js

class App {
  ...
  addObj() {
    // 几何球体
    const geometry = new THREE.SphereBufferGeometry(30, 64, 64);

    // 材质
    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

    // 网格
    var mesh = new THREE.Mesh(geometry, material);
    mesh.name = "spare"
    this.scene.add(mesh);
  }
}

创建一个球体:
在这里插入图片描述

2、使用着色器材质

这个也是基础工作。
App.js

import { fragmentShader } from './glsl.fragmentShader.js'
import { vertexShader } from './glsl.vertexShader.js'
class App {
  addObj() {
    ...
    // 材质
    var material = new THREE.ShaderMaterial({
      uniforms: this.uniforms,
      vertexShader: vertexShader,
      fragmentShader: fragmentShader
    });
    ...
  }
}

glsl.vertexShader.js

export let vertexShader = `
// 这里使用 uv,将传给片元着色器使用。
varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec(position, 1.0);
}
`

glsl.fragmentShader.js, 这里先设置为白色。

export let fragmentShader = `
varying vec2 vUv;
void main() {
  gl_FragColor = vec4(1.);
}
`

在这里插入图片描述

3、绘制网格

重点终于来了!

1)感受一下uv
export let fragmentShader = `
varying vec2 vUv;
void main() {
  gl_FragColor = vec4(vec3(vUv.x), 1.0);
}
`

uv.x 范围是从0~1,那么体现在球体的x方向,颜色就是从黑色到白色。uv.y同理。
在这里插入图片描述

2)绘制一条线

根据uv坐标的特性,对uv坐标进行不同处理,那么就可以绘制线了。

export let fragmentShader = `
varying vec2 vUv;
void main() {
  float lineWidth = 0.01;
  if(vUv.x<lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

在这里插入图片描述

3) 绘制多条线

uv坐标有超出重复的特性,比如说:

默认uv的坐标范围是0~1,如果超出1,就会重复贴图。

varying vec2 vUv;
void main() {
  // 线的数量
  float lineNumber = 5.0;
  // 线的宽度
  float lineWidth = 0.01;

  // 取uv.x 的小数部分
  float x = fract(vUv.x * lineNumber);
  if(x<lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

这样就会出现多条线:
在这里插入图片描述

4、绘制经纬线

有了前面的基础,那么经纬线就很好绘制了。

varying vec2 vUv;
void main() {
  float lineNumber = 20.0;
  float lineWidth = 0.01;
  float x = fract(vUv.x * lineNumber);
  float y = fract(vUv.y * lineNumber);
  if(x<lineWidth || y <lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

最终效果:
在这里插入图片描述

<全文结束, 多多点赞会变好看, 多多评论会变有钱>

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是一个使用 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() 函数绘制二次贝塞尔曲线。 这个代码示例只是一个开始,你可以使用类似的方法绘制更复杂的二次或三次贝塞尔曲线,或者使用其他类型的曲线。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值