Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.11.2017, 08:27   #61
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

WebGL 1.0. Наложение текстуры на квадрат

https://jsfiddle.net/zjydm1ev/

026_applying_a_texture_to_a_square.jpg

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebGL 1.0. Applying a texture to a square</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `
            attribute vec2 a_Position;
            attribute vec2 a_TexCoord;
            uniform mat4 u_ModelMatrix;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
                v_TexCoord = a_TexCoord;
            }`;

        var fragmentShaderSource =
            `
            precision mediump float;
            uniform sampler2D u_Sampler;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_FragColor = texture2D(u_Sampler, v_TexCoord);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        var FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        var image = new Image();

        image.onload = function ()
        {
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.activeTexture(gl.TEXTURE0);

            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

            var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
            gl.uniform1i(u_Sampler, 0);

            var modelMatrix = mat4.create();
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1.5, 1.5, 1.5));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        image.crossOrigin = "";
        image.src = 'https://dl.dropboxusercontent.com/s/xi091ya34qqzda2/lightblueflower.jpg';
    </script>
</body>

</html>
8Observer8 вне форума Ответить с цитированием
Старый 30.11.2017, 08:31   #62
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

WebGL 2.0. Наложение текстуры на квадрат

https://jsfiddle.net/gd2uo3jg/

026_applying_a_texture_to_a_square.jpg

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebGL 2.0. Applying a texture to a square</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `#version 300 es

            in vec2 a_Position;
            in vec2 a_TexCoord;
            uniform mat4 u_ModelMatrix;
            out vec2 v_TexCoord;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
                v_TexCoord = a_TexCoord;
            }`;

        var fragmentShaderSource =
            `#version 300 es

            precision mediump float;
            uniform sampler2D u_Sampler;
            in vec2 v_TexCoord;
            out vec4 fragColor;

            void main()
            {
                fragColor = texture(u_Sampler, v_TexCoord);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl2");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        var FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        var image = new Image();

        image.onload = function ()
        {
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.activeTexture(gl.TEXTURE0);

            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D , 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

            var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
            gl.uniform1i(u_Sampler, 0);

            var modelMatrix = mat4.create();
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1.5, 1.5, 1.5));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        image.crossOrigin = "";
        image.src = 'https://dl.dropboxusercontent.com/s/xi091ya34qqzda2/lightblueflower.jpg';
    </script>
</body>

</html>
8Observer8 вне форума Ответить с цитированием
Старый 08.12.2017, 22:54   #63
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

WebGL 1.0. Анимация вращения

https://jsfiddle.net/8Observer8/gLpowbe2/

ezgif.com-optimize.gif

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebGL 1.0. Rotation animation</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #a8bdc4;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `attribute vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `precision mediump float;
            uniform vec3 u_Color;

            void main()
            {
                gl_FragColor = vec4(u_Color, 1.0);
            }`;

        var canvas = document.getElementById("renderCanvas");
        var gl = canvas.getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.207, 0.635, 0.125);

        var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");

        gl.clearColor(0.894, 0.976, 0.886, 1.0);

        var ANGLE_STEP = 45.0; // Rotation angle (degrees/second)
        var g_last = Date.now();

        var currentAngle = 0.0;
        var modelMatrix = mat4.create();

        var tick = function ()
        {
            currentAngle = animate(currentAngle);  // Update the rotation angle
            draw(4, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
            requestAnimationFrame(tick, canvas); // Request that the browser calls tick
        };
        tick();

        function draw(n, currentAngle, modelMatrix, u_ModelMatrix)
        {
            mat4.identity(modelMatrix);
            mat4.rotateZ(modelMatrix, modelMatrix, currentAngle * Math.PI / 180);
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
        }

        function animate(angle)
        {
            // Calculate the elapsed time
            var now = Date.now();
            var elapsed = now - g_last;
            g_last = now;
            // Update the current rotation angle (adjusted by the elapsed time)
            var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
            return newAngle %= 360;
        }
    </script>
</body>

</html>

Последний раз редактировалось 8Observer8; 08.12.2017 в 22:59.
8Observer8 вне форума Ответить с цитированием
Старый 09.12.2017, 00:07   #64
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

WebGL 2.0. Анимация вращения

https://jsfiddle.net/8Observer8/fLumroxa/

ezgif.com-optimize.gif

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebGL 2.0. Rotation animation</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #a8bdc4;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `#version 300 es

            in vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `#version 300 es
            
            precision mediump float;
            uniform vec3 u_Color;
            out vec4 fragColor;

            void main()
            {
                fragColor = vec4(u_Color, 1.0);
            }`;

        var canvas = document.getElementById("renderCanvas");
        var gl = canvas.getContext("webgl2");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.207, 0.635, 0.125);

        var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");

        gl.clearColor(0.894, 0.976, 0.886, 1.0);

        var ANGLE_STEP = 45.0; // Rotation angle (degrees/second)
        var g_last = Date.now();

        var currentAngle = 0.0;
        var modelMatrix = mat4.create();

        var tick = function ()
        {
            currentAngle = animate(currentAngle);  // Update the rotation angle
            draw(4, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
            requestAnimationFrame(tick, canvas); // Request that the browser calls tick
        };
        tick();

        function draw(n, currentAngle, modelMatrix, u_ModelMatrix)
        {
            mat4.identity(modelMatrix);
            mat4.rotateZ(modelMatrix, modelMatrix, currentAngle * Math.PI / 180);
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
        }

        function animate(angle)
        {
            // Calculate the elapsed time
            var now = Date.now();
            var elapsed = now - g_last;
            g_last = now;
            // Update the current rotation angle (adjusted by the elapsed time)
            var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
            return newAngle %= 360;
        }
    </script>
</body>

</html>
8Observer8 вне форума Ответить с цитированием
Старый 09.01.2018, 23:00   #65
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Вывод текста

Живая демка + исходники: https://plnkr.co/edit/GqmJ4uB5XmNB1Cu7qlhl?p=preview
Скачать исходники архивом: drawing-text.zip

Шрифты были созданы из TrueType и OpenType с помощью программы Bitmap Font Generator

DrawingText2-optimize.gif
8Observer8 вне форума Ответить с цитированием
Старый 20.12.2020, 15:38   #66
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Установка системы координат в 2D

534cdc95-6487-44f0-b33c-b9573873c842.png

С помощью ортогональной матрицы проекции из библиотеки glMatrix можно установить начало системы координат в любую точку на холсте, а также указать направления осей (выбрать правую или левую систему координат, то есть, которую можно определить с помощью правила правой или левой руки) и установить диапазон по осям: X, Y, Z.

Например, следующая строка кода:

Код:
glMatrix.mat4.ortho(projMatrix, 0, 10, 10, 0, -50, 50);
создаёт матрицу проекции, которая:
  • задаёт начало системы координат в центре холста
  • устанавливает диапазон по X, Y и Z
  • выбирает правую систему координат, которая определяется по правилу правой руки. Ось X направлена вправо, ось Y направлена вверх, ось Z направлена на наблюдателя

В примере ниже система координат установлена в верхний левый угол в диапазоне [0, 10], используя левую систему координат (ось X направлена вправо, ось Y направлена вниз, ось Z направлена на наблюдателся). Размер квадрата равен одному, угол поворота равен 0 градусов (вокруг оси Z), координата квадрата (его левого верхнего угла) равна (3, 2). В примере создаются матрицы: размера, поворота и перемещения, проекции, а также матрица вида. Эти матрицы перемножаются друг на друга в порядке: projMatrix * viewMatrix * modelMatrix. Матрица modelMatrix хранит три вида трансформаций, которые применяются справа налево: Scaling * Rotation * Translation

Код:
        glMatrix.mat4.ortho(projMatrix, 0, 10, 10, 0, -50, 50);
        glMatrix.mat4.lookAt(viewMatrix, [0, 0, 40], [0, 0, 0], [0, 1, 0]);
        glMatrix.mat4.scale(modelMatrix, modelMatrix, glMatrix.vec3.fromValues(1, 1, 1));
        glMatrix.mat4.translate(modelMatrix, modelMatrix, glMatrix.vec3.fromValues(3, 2, 0));
        glMatrix.mat4.rotate(modelMatrix, modelMatrix, 0 * Math.PI / 180, glMatrix.vec3.fromValues(0, 0, 1));
        glMatrix.mat4.mul(mpMatrix, projMatrix, modelMatrix);
Запустить в песочнице: https://plnkr.co/edit/ypo8IICJrMpVsRLA?preview

index.html

Код:
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Set 2D Coord System. WebGL 1.0, JavaScript</title>
    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix-min.js"></script>
</head>
 
<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>
 
    <script type="x-shader/x-vertex" id="vertexShader">
        attribute vec3 aPosition;
        uniform mat4 uMvpMatrix;
        void main()
        {
            gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
        }
    </script>
 
    <script type="x-shader/x-fragment" id="fragmentShader">
        void main()
        {
            gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);
        }
    </script>
 
    <script>
        const gl = document.getElementById("renderCanvas").getContext("webgl");
        const program = createProgram();
        const n = initVertexBuffers(program);
        const mpMatrix = glMatrix.mat4.create();
        const projMatrix = glMatrix.mat4.create();
        const viewMatrix = glMatrix.mat4.create();
        const modelMatrix = glMatrix.mat4.create();
 
        glMatrix.mat4.ortho(projMatrix, 0, 10, 10, 0, -50, 50);
        glMatrix.mat4.lookAt(viewMatrix, [0, 0, 40], [0, 0, 0], [0, 1, 0]);
        glMatrix.mat4.scale(modelMatrix, modelMatrix, glMatrix.vec3.fromValues(1, 1, 1));
        glMatrix.mat4.translate(modelMatrix, modelMatrix, glMatrix.vec3.fromValues(3, 2, 0));
        glMatrix.mat4.rotate(modelMatrix, modelMatrix, 0 * Math.PI / 180, glMatrix.vec3.fromValues(0, 0, 1));
        glMatrix.mat4.mul(mpMatrix, projMatrix, modelMatrix);
        const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
        gl.uniformMatrix4fv(uMvpMatrixLocation, false, mpMatrix);
 
        gl.clearColor(0.2, 0.2, 0.2, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 
        function initVertexBuffers(program)
        {
            const vertPositions = new Float32Array([
                0, 1, 0,
                1, 1, 0,
                0, 0, 0,
                1, 0, 0
            ]);
            const vertPosBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, vertPositions, gl.STATIC_DRAW);
            gl.bindAttribLocation(program, 0, "aPosition");
            gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(0);
        }
        
        function createProgram()
        {
            const vShaderSource = document.getElementById("vertexShader").firstChild.textContent;
            const vShader = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vShader, vShaderSource);
            gl.compileShader(vShader);
            const fShaderSource = document.getElementById("fragmentShader").firstChild.textContent;
            const fShader = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fShader, fShaderSource);
            gl.compileShader(fShader);
            const program = gl.createProgram();
            gl.attachShader(program, vShader);
            gl.attachShader(program, fShader);
            gl.linkProgram(program);
            gl.useProgram(program);
            return program;
        }
    </script>
</body>
 
</html>
8Observer8 вне форума Ответить с цитированием
Старый 20.12.2020, 15:40   #67
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Установка системы координат в 2D на OpenGL ES 2.0 и Qt C++

В качестве бонуса тот же пример, что и выше, но на OpenGL ES 2.0 и Qt C++ (шейдеры один в один), который можно скомпилировать под Windows, Linux, macOS, Android и iOS.

Сборка в релиз для Windows: Set2DCoordSystem_EXE.zip (11.08 Мб)



main.cpp

Код:
// Add this line to .pro:
// win32: LIBS += -lopengl32

#ifdef _WIN32
#include <windows.h>
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif

#include <QtWidgets/QApplication>
#include <QtWidgets/QOpenGLWidget>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLBuffer>
#include <QtGui/QMatrix4x4>

class Widget : public QOpenGLWidget {
    Q_OBJECT
public:
    Widget() {
        setWindowTitle("OpenGL ES 2.0 Qt C++");
        resize(400, 400);
    }
private:
    QOpenGLShaderProgram m_program;
    QOpenGLBuffer m_vertPosBuffer;
    QMatrix4x4 m_mvpMatrix;
    QMatrix4x4 m_projMatrix;
    QMatrix4x4 m_viewMatrix;
    QMatrix4x4 m_modelMatrix;
    int m_uMvpMatrixLocation;
    const float WORLD_HEIGHT = 10;

    void initializeGL() override {
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        const char *vertShaderSrc =
                "attribute vec3 aPosition;\n"
                "uniform mat4 uMvpMatrix;\n"
                "void main()\n"
                "{\n"
                "    gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
                "}\n";
        const char *fragShaderSrc =
                "void main()\n"
                "{\n"
                "    gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);\n"
                "}\n";
        m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertShaderSrc);
        m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShaderSrc);
        m_program.link();
        m_program.bind();
        float vertPositions[] = {
            0.f, 1.f, 0.f,
            1.f, 1.f, 0.f,
            0.f, 0.f, 0.f,
            1.f, 0.f, 0.f
        };
        initVertexBuffer(m_vertPosBuffer, vertPositions, sizeof(vertPositions), "aPosition", 0, 3);
        m_program.bind();
        m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
        m_viewMatrix.lookAt(QVector3D(0.f, 0.f, 40.f),
                            QVector3D(0.f, 0.f, 0.f),
                            QVector3D(0.f, 1.f, 0.f));
        m_modelMatrix.scale(QVector3D(1.f, 1.f, 1.f));
        m_modelMatrix.translate(QVector3D(3.f, 2.f, 0.f));
        m_modelMatrix.rotate(0.0f, QVector3D(0.f, 0.f, 1.f));
    }
    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT);
        m_mvpMatrix = m_projMatrix * m_viewMatrix * m_modelMatrix;
        m_program.bind();
        m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    }
    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h);
        float aspect = (float) w / h;
        float worldWidth = aspect * WORLD_HEIGHT;
        m_projMatrix.setToIdentity();
        m_projMatrix.ortho(0.f, worldWidth, WORLD_HEIGHT, 0.f, 50.f, -50.f);
    }
    void initVertexBuffer(QOpenGLBuffer &buffer, float data[], int amount,
                          const char *locationName, int locationIndex, int tupleSize) {
        buffer.create();
        buffer.bind();
        buffer.allocate(data, amount);
        m_program.bindAttributeLocation(locationName, locationIndex);
        m_program.setAttributeBuffer(locationIndex, GL_FLOAT, 0, tupleSize);
        m_program.enableAttributeArray(locationIndex);
    }
};

#include "main.moc"

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
8Observer8 вне форума Ответить с цитированием
Старый 13.01.2021, 23:26   #68
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Рисование квадратов, координаты которых считываются с удалённой базы данных MySQL и передаются с сервера через WebSocket

Развернул пример на бесплатном хостинге Heroku: https://squares-from-mysql-webgl10-js.herokuapp.com/

d9e69a40-3401-41fc-aba4-ac5d616753fa.png

Ограничение на бесплатном хостинге Heroku такое, что если приложением не пользовались 30 минут, то оно засыпает, но чтобы приложение проснулось достаточно 10-15 секунд. В настройках приложения на Heroku я соединил приложение с репозиторием на GitHub, чтобы происходило автоматическое развёртывание после каждого коммита (git push).

Скачать исходники: squares-from-mysql-webgl10-js.zip (3.5 Кб)

Команда для создания базы данных из HeidiSQL:

Код:
CREATE TABLE squares (id INTEGER AUTO_INCREMENT PRIMARY KEY, x FLOAT, y FLOAT);
INSERT INTO squares (x, y) VALUES (0, 1);
INSERT INTO squares (x, y) VALUES (3, 4);
INSERT INTO squares (x, y) VALUES (8, 8);
Клиент подключается к серверу через WebSocket. Сервер в обработчике подключения клиента отсылает ему через сокет массив координат квадратов, считанных из базы данных MySQL. Если у вас нет опыта работы с MySQL из Node.js, то рекомендую начать с туториалов на сайте Metanit:

Для работы с базой данных MySQL использую бесплатную легковесную программу HeidiSQL. Metanit использует "MySQL Workbench", но Workbench занимает очень много места на жёстком, по-моему, в районе 1 ГБайт и много оперативной памяти, а HeidiSQL занимает на жёстком всего 33.2 МБ и 26.5 МБайт оперативной памяти.

Исходники:

index.html

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Triangles from DB. WebGL 1.0, JavaScript</title>
    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix-min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>

    <script type="x-shader/x-vertex" id="vertexShader">
        attribute vec3 aPosition;
        uniform mat4 uMvpMatrix;
        void main()
        {
            gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
        }
    </script>

    <script type="x-shader/x-fragment" id="fragmentShader">
        void main()
        {
            gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);
        }
    </script>

    <script>
        const gl = document.getElementById("renderCanvas").getContext("webgl");
        const program = createProgram();
        const n = initVertexBuffers(program);
        const mpMatrix = glMatrix.mat4.create();
        const projMatrix = glMatrix.mat4.create();
        const viewMatrix = glMatrix.mat4.create();
        const modelMatrix = glMatrix.mat4.create();
        let coords;

        function main()
        {
            const socket = new WebSocket("ws://localhost:3000");
            // const socket = new WebSocket("wss://squares-from-mysql-webgl10-js.herokuapp.com");

            socket.onopen = () =>
            {
                console.log("Client connected");

                socket.onmessage = (event) =>
                {
                    coords = JSON.parse(event.data);
                    draw();
                };
            };
        }
        window.onload = () => main();

        function draw()
        {
            glMatrix.mat4.ortho(projMatrix, 0, 10, 10, 0, -50, 50);
            glMatrix.mat4.lookAt(viewMatrix, [0, 0, 40], [0, 0, 0], [0, 1, 0]);

            gl.clearColor(0.2, 0.2, 0.2, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            coords.forEach(c =>
            {
                glMatrix.mat4.fromScaling(modelMatrix, glMatrix.vec3.fromValues(1, 1, 1));
                glMatrix.mat4.translate(modelMatrix, modelMatrix, glMatrix.vec3.fromValues(c.x, c.y, 0));
                glMatrix.mat4.rotate(modelMatrix, modelMatrix, 0 * Math.PI / 180, glMatrix.vec3.fromValues(0, 0, 1));
                glMatrix.mat4.mul(mpMatrix, projMatrix, modelMatrix);
                const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
                gl.uniformMatrix4fv(uMvpMatrixLocation, false, mpMatrix);
                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
            });
        }

        function initVertexBuffers(program)
        {
            const vertPositions = new Float32Array([
                0, 1, 0,
                1, 1, 0,
                0, 0, 0,
                1, 0, 0
            ]);
            const vertPosBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, vertPositions, gl.STATIC_DRAW);
            gl.bindAttribLocation(program, 0, "aPosition");
            gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(0);
        }

        function createProgram()
        {
            const vShaderSource = document.getElementById("vertexShader").firstChild.textContent;
            const vShader = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vShader, vShaderSource);
            gl.compileShader(vShader);
            const fShaderSource = document.getElementById("fragmentShader").firstChild.textContent;
            const fShader = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fShader, fShaderSource);
            gl.compileShader(fShader);
            const program = gl.createProgram();
            gl.attachShader(program, vShader);
            gl.attachShader(program, fShader);
            gl.linkProgram(program);
            gl.useProgram(program);
            return program;
        }
    </script>
</body>

</html>
app.js

Код:
const express = require("express");
const http = require("http");
const path = require("path");
const WebSocket = require("ws");
const mysql = require("mysql2");

const app = express();
app.use(express.static(path.join(__dirname, "../../public")));
app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "../../public/index.html")); });

const httpServer = http.createServer(app);
const wss = new WebSocket.Server({ server: httpServer });

wss.on("connection", (socket) =>
{
    console.log("Client connected");

    // Local host
    const pool = mysql.createPool({
        connectionLimit: 10,
        host: "localhost",
        user: "root",
        password: "your_password",
        database: "squares_db"
    }).promise();

    pool.query("select * from squares")
        .then(result =>
        {
            console.log(result[0]);
            socket.send(JSON.stringify(result[0]));
        })
        .catch(err =>
        {
            console.log(err.message);
        });
});

const port = process.env.PORT || 3000;
httpServer.listen(port, () =>
{
    console.log("Server started. Port:", port);
});
package.json

Код:
{
  "name": "squares-from-db-webgl10-js",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node src/server/app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "mysql2": "^2.2.5",
    "ws": "^7.3.1"
  }
}
Вложения
Тип файла: zip squares-from-mysql-webgl10-js.zip (3.5 Кб, 1 просмотров)

Последний раз редактировалось 8Observer8; 14.01.2021 в 13:43.
8Observer8 вне форума Ответить с цитированием
Старый 17.01.2021, 21:48   #69
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Пример на JavaScript, Python и C++, в которым определяется клик мыши по фигуре любой формы, как в 2D, так и в 3D

pick-triangle-webgl10-js.gif

Запустить демку в браузере:
Исходники:
8Observer8 вне форума Ответить с цитированием
Старый 18.01.2021, 21:27   #70
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Спрайтовая анимация на Canvas API на JavaScript, Python и C++

Запустить демку в браузере в песочнице Plunker: https://plnkr.co/edit/zjYT0KTfj50MejT9?preview

animation-canvas2d-js.gif


Данный пример не использует WebGL, но он очень кратно демонстрирует принцип спрайтовой анимации. Попробуйте реализовать этот принцип самостоятельно на WebGL и OpenGL. Лучший способ изучения - это написание кода самостоятельно с нуля до перехода знаний в навыки через многократное повторение изученного на практике. У меня есть короткий пример спрайтовой анимации на WebGL и OpenGL, но я его пока выкладывать не буду, чтобы у вас было время попробовать самостоятельно решить эту задачу.

JavaScript, Canvas2D

index.html

Код:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Running Cat. Canvas API, JavaScript</title>
    <script src="js/main.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="512" height="256"></canvas>
</body>

</html>
main.js

Код:

window.onload = () =>
{
    const ctx = document.getElementById("renderCanvas").getContext("2d");

    let sx = 0, sy = 0, sWidth = 512, sHeight = 256; // Source image
    let dx = 0, dy = 0, dWidth = 512, dHeight = 256; // Destination canvas
    // ctx.drawImage(spriteSheet, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

    const spriteSheet = new Image();
    spriteSheet.onload = () => { mainLoop(); };
    spriteSheet.src = "assets/sprites-cat-running.png";

    let currentTime, deltaTime;
    let lastTime = Date.now();
    let animationTime = 0;
    const animationSpeed = 100;
    const frames = [
        { x: 0, y: 0 }, { x: sWidth, y: 0 }, { x: sWidth * 2, y: 0 }, { x: sWidth * 3, y: 0 },
        { x: 0, y: sHeight }, { x: sWidth, y: sHeight }, { x: sWidth * 2, y: sHeight },
        { x: sWidth * 3, y: sHeight }
    ];

    let i = 0; // Frame index

    function mainLoop()
    {
        currentTime = Date.now();
        deltaTime = currentTime - lastTime;
        lastTime = currentTime;

        animationTime += deltaTime;
        if (animationTime >= animationSpeed)
        {
            animationTime = 0;
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            ctx.drawImage(spriteSheet, frames[i].x, frames[i].y, sWidth, sHeight, dx, dy, dWidth, dHeight);
            i++;
            if (i >= frames.length) { i = 0; }
        }
        requestAnimationFrame(mainLoop);
    }
};
Python, PyQt5, QPainter

Код:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QImage
from PyQt5.QtCore import QTimer, QElapsedTimer, QPoint

class Window(QWidget):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5")
        self.resize(512, 256)
        # Download a sprite sheet here:
        # https://plnkr.co/edit/zjYT0KTfj50MejT9?preview
        self.sprite_sheet = QImage("sprites-cat-running.png")
        self.sw = 512
        self.sh = 256
        self.frame_index = 0
        self.x = 0
        self.y = 0
        self.frames = []
        for i in range(2):
            for j in range(4):
                self.frames.append(QPoint(j * self.sw, i * self.sh))
        self.delta_time = 0
        self.animation_time = 0
        self.animation_speed = 100
        self.timer = QTimer()
        self.timer.timeout.connect(self.animationLoop)
        self.elapsedTimer = QElapsedTimer()
        self.timer.start(1000/60)
        
    def animationLoop(self):
        self.delta_time = self.elapsedTimer.elapsed()
        self.elapsedTimer.restart()
        self.animation_time += self.delta_time
        if self.animation_time >= self.animation_speed:
            self.animation_time = 0
            self.x = self.frames[self.frame_index].x()
            self.y = self.frames[self.frame_index].y()
            self.frame_index += 1
            if self.frame_index >= len(self.frames):
                self.frame_index = 0
        self.update()

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.drawImage(0, 0, self.sprite_sheet, self.x, self.y, self.sw, self.sh)

def main():
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
Python, PySide2, QPainter

Код:
import sys
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtGui import QPainter, QImage
from PySide2.QtCore import QTimer, QElapsedTimer, QPoint

class Window(QWidget):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("PySide2")
        self.resize(512, 256)
        # Download a sprite sheet here:
        # https://plnkr.co/edit/zjYT0KTfj50MejT9?preview
        self.sprite_sheet = QImage("sprites-cat-running.png")
        self.sw = 512
        self.sh = 256
        self.frame_index = 0
        self.x = 0
        self.y = 0
        self.frames = []
        for i in range(2):
            for j in range(4):
                self.frames.append(QPoint(j * self.sw, i * self.sh))
        self.delta_time = 0
        self.animation_time = 0
        self.animation_speed = 100
        self.timer = QTimer()
        self.timer.timeout.connect(self.animationLoop)
        self.elapsedTimer = QElapsedTimer()
        self.timer.start(1000/60)
        
    def animationLoop(self):
        self.delta_time = self.elapsedTimer.elapsed()
        self.elapsedTimer.restart()
        self.animation_time += self.delta_time
        if self.animation_time >= self.animation_speed:
            self.animation_time = 0
            self.x = self.frames[self.frame_index].x()
            self.y = self.frames[self.frame_index].y()
            self.frame_index += 1
            if self.frame_index >= len(self.frames):
                self.frame_index = 0
        self.update()

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.drawImage(0, 0, self.sprite_sheet, self.x, self.y, self.sw, self.sh)

def main():
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
продолжение в следующем сообщении

Последний раз редактировалось 8Observer8; 19.01.2021 в 01:40.
8Observer8 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
WebGL developer Ojoteam Фриланс 0 19.05.2017 12:37
Ищу моделера для браузерной WebGL игры Kempston Gamedev - cоздание игр: Unity, OpenGL, DirectX 0 31.03.2016 21:23
Пример использования Gera WebGL 3D Library rekodDeveloper JavaScript, Ajax 5 02.06.2015 16:05
Вопрос по Webgl Halk_blr Помощь студентам 0 23.02.2014 23:19
WebGl, использование Three.js оптимизировать и подправить код dem66 JavaScript, Ajax 0 23.06.2012 20:14