如何使用多个对象创建球体 [英] How to create sphere using multiple objects

查看:89
本文介绍了如何使用多个对象创建球体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用多个方块绘制球体(我也允许使用三角形,但我发现一些现有的代码用于方形帮助,所以我用它)。我已成功绘制了多个正方形(5000)。但我不必使用任何inbuit函数来创建球体。我的代码如下:

I have to draw sphere using multiple squares(i am also allowed to use triangles even, but i found some existing code for help in square, so i used it). I have successfully drawn multiple squares (5000).But i don't have to use any inbuit function to create sphere . My code is below :

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script class="WebGL">
        var gl;
        function createProgram(gl, vertexShader, fragmentShader)
        {
            var vs = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vs, vertexShader);
            gl.compileShader(vs);

            if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(vs));
            //////
            var fs = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fs, fragmentShader);
            gl.compileShader(fs);

            if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(fs));
            program = gl.createProgram();
            gl.attachShader(program, vs);
            gl.attachShader(program, fs);
            gl.linkProgram(program);
            if (!gl.getProgramParameter(program, gl.LINK_STATUS))
                alert(gl.getProgramInfoLog(program));
            return program;
        }
        function createShaderFromScriptElement(gl , shaderName)
        {
            var Shader = document.getElementById(shaderName).firstChild.nodeValue;
            return Shader;
        }
        function start()
        {
            var canvas = document.getElementById("canvas");
            gl = canvas.getContext("experimental-webgl");
            if (!gl) { alert("error while GL load"); }

              var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
              var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");

              var program = createProgram(gl, vertexShader, fragmentShader);

            gl.useProgram(program);
            var positionLocation = gl.getAttribLocation(program, "a_position");
            var colorLocation = gl.getUniformLocation(program, "u_color");
            var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

            var buffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
            gl.uniform2f(resolutionLocation, 200, 200);

            gl.enableVertexAttribArray(positionLocation);
            gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
            for (var ii = 0; ii < 5000; ++ii)
            {
                // Setup a random rectangle
                setRectangle(gl, randomInt(300), randomInt(300), 10, 10);
                // Set a random color.
                gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);
                // Draw the rectangle.
                gl.drawArrays(gl.TRIANGLES, 0, 6);
            }
            function randomInt(range)
            {
                return Math.floor(Math.random() * range);
            }

            // Fills the buffer with the values that define a rectangle.
            function setRectangle(gl, x, y, width, height)
            {
                var x1 = x;
                var x2 = x + width;
                var y1 = y;
                var y2 = y + height;
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
                   x1, y1,
                   x2, y1,
                   x1, y2,
                   x1, y2,
                   x2, y1,
                   x2, y2]), gl.STATIC_DRAW);
            }
        }
    </script>
    <script id="2d-vertex-shader" type="x-shader/x-vertex">
        attribute vec2 a_position;
        uniform vec2 u_resolution;

        void main() {
        // convert the rectangle from pixels to 0.0 to 1.0
        vec2 zeroToOne = a_position / u_resolution;

        // convert from 0->1 to 0->2
        vec2 zeroToTwo = zeroToOne * 2.0;

        // convert from 0->2 to -1->+1 (clipspace)
        vec2 clipSpace = zeroToTwo - 1.0;

        gl_Position = vec4(clipSpace* vec2(1, -1), 0, 1);
        }
    </script>

    <script id="2d-fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        uniform vec4 u_color;

        void main()
        {
        gl_FragColor = u_color;  // green
        }
    </script>
</head>
<body onload="start()">
    <div style="text-align: center">
        <canvas id="canvas" width="1000" height="800"></canvas>
    </div>
</body>
</html>

我要的是使用多个对象绘制球体,我不知道该怎么做。并且我尝试首先绘制多个对象(在我的情况下为5000),然后尝试使用它绘制球体(我的意思是使用这5000个方块,我的下一步是创建球体)。

What i am asked is to draw sphere using multiple objects which i have no idea how to do.And my try was first to draw the multiple objects (5000 in my case) and then try for drawing sphere using it(i mean using these 5000 squares, my next step is to create sphere).

但是我不知道如何继续使用这些方块绘制球体?

But i don't know how to proceed further to draw sphere using these squares ?

我是谁不能理解怎么做。有人可以帮助我吗?

Which i am not able to understand how to do. Could some one please help me ?

推荐答案

其中一种方法是在顶点着色器中使用矩形切片构造球体。

One of approaches is constructing sphere from rectangular tiles in vertex shader.

一般情况下,用瓦片覆盖 [0,2 * M_PI] x [0,M_PI] 区域。比如,你有 N 瓦片,其中 N = m * k m 是一行中的瓦片数量, k 是列中的瓷砖数量。

Generally, the thing is to cover [0, 2*M_PI] x [0, M_PI] region with tiles. Say, you have N tiles where N = m*k, m is amount of tiles in a row and k is amount of tiles in column.

您可以创建 N 单位正方形,并为每个单位正方形分配 m * k 矩阵中的唯一位置。然后将这些位置和平铺的宽度/高度( 2 * M_PI / m M_PI / k )作为制服传递给顶点着色器(或作为属性)。

You could create N unit squares and assign to each of them its unique position in m * k matrix. Then pass these positions and width/height of tiles (2*M_PI / m and M_PI / k) as uniforms to vertex shader (or as attributes).

在顶点着色器中知道贴片的位置及其宽度/高度计算顶点的坐标在 [0,2 * M_PI] x [0,M_PI] (它们会 phi ksi )。然后计算球体上的实际顶点位置:

In vertex shader knowing position of tile and its width/height compute vertice's coords on [0, 2*M_PI] x [0, M_PI] (they would be phi and ksi). And then compute actual vertex position on sphere:

coord.x = sin(ksi) * cos(phi);
coord.y = sin(ksi) * sin(phi);
coord.z = cos(ksi);

另请注意,您应为此设置透视投影。

Also note you should set up perspective projection for this.

选择 m k 取决于您(毕竟有素数)。我建议从方形瓷砖开始。以下是我得到的结果图片:

Choosing m and k is up to you (there are prime numbers after all). I recommend to start with square tiles. Here is the picture of result i got this way:

这篇关于如何使用多个对象创建球体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆