批处理之家's Archiver

523066680 发表于 2017-7-7 15:41

Html5 Canvas + WebGL 简单示例

[size=2][b]HTML5 Canvas 示例[/b][/size][list][list]

[list][list][table=60%, #f8f8f8][tr][td][font=consolas][size=2][font=consolas][size=3][color=#008000][b]<!DOCTYPE[/b][/color] html[color=#008000][b]>[/b][/color]
[color=#008000][b]<html[/b][/color] [color=#b00040]lang[/color]=[color=#ba2121]"en"[/color][color=#008000][b]>[/b][/color]
  [color=#008000][b]<head>[/b][/color]
    [color=#008000][b]<meta[/b][/color] [color=#b00040]charset[/color]=[color=#ba2121]"utf-8"[/color] [color=#008000][b]/>[/b][/color]
    [color=#008000][b]<title>[/b][/color]Canvas[color=#008000][b]</title>[/b][/color]
  [color=#008000][b]</head>[/b][/color]

  [color=#008000][b]<body[/b][/color] [color=#b00040]onload[/color]=[color=#ba2121]"main()"[/color][color=#008000][b]>[/b][/color]
    [color=#008000][b]<canvas[/b][/color] [color=#b00040]id[/color]=[color=#ba2121]"example1"[/color] [color=#b00040]width[/color]=[color=#ba2121]"400"[/color] [color=#b00040]height[/color]=[color=#ba2121]"400"[/color][color=#008000][b]>[/b][/color]
      Please use a browser that supports [color=#ba2121]"canvas"[/color]
    [color=#008000][b]</canvas>[/b][/color]
    [color=#008000][b]<script>[/b][/color]
      [color=#008000][b]function[/b][/color] [color=#555555]main[/color][color=#555555]()[/color]
      [color=#555555]{[/color]
        [color=#008000][b]var[/b][/color] canvas [color=#555555]=[/color] document[color=#555555].[/color][color=#555555]getElementById[/color][color=#555555]([/color][color=#ba2121]'example1'[/color][color=#555555]);[/color]
        [color=#008000][b]if[/b][/color] [color=#555555](![/color] canvas [color=#555555])[/color]
        [color=#555555]{[/color]
          console[color=#555555].[/color][color=#555555]log[/color][color=#555555]([/color][color=#ba2121]'Failed to retrieve the <canvas> element'[/color][color=#555555]);[/color]
          [color=#008000][b]return[/b][/color][color=#555555];[/color]
        [color=#555555]}[/color]
        
        [color=#008000][b]var[/b][/color] ctx [color=#555555]=[/color] canvas[color=#555555].[/color][color=#555555]getContext[/color][color=#555555]([/color][color=#ba2121]'2d'[/color][color=#555555]);[/color]      [color=#408080][i]// 注意是小写'd'[/i][/color]
        
        ctx[color=#555555].[/color]fillStyle [color=#555555]=[/color] [color=#ba2121]'rgba(0, 0, 255, 1.0)'[/color][color=#555555];[/color] [color=#408080][i]//设置填充颜色[/i][/color]
        ctx[color=#555555].[/color][color=#555555]fillRect[/color][color=#555555]([/color][color=#666666]120[/color][color=#555555],[/color] [color=#666666]10[/color][color=#555555],[/color] [color=#666666]150[/color][color=#555555],[/color] [color=#666666]150[/color][color=#555555]);[/color]        [color=#408080][i]//矩形填充,设置范围[/i][/color]
      [color=#555555]}[/color]
    [color=#008000][b]</script>[/b][/color]
  [color=#008000][b]</body>[/b][/color]
[color=#008000][b]</html>[/b][/color][/size][/font][/size][/font][/b][/td][/tr][/table][/list][/list]
在线展示:
[url]http://runjs.cn/code/8r9cqjly[/url]

通过 var canvas = document.getElementById('example1') 获取指定id的 canvas 元素,
ID名称 example1 和前面的 <canvas id="example1" width="400" height="400"> 相对应 ,
其中 width 和 height 指定了画布尺寸。

然后获取 2d 绘制环境 var ctx = canvas.getContext('2d');

接下来对这个代码进行修改,仍旧需要 html5 画布作为基础,但是渲染环境改为 WebGL

[list][list][table=60%, #f8f8f8][tr][td][font=consolas][size=2][font=consolas][size=3][color=#008000][b]<html[/b][/color] [color=#b00040]lang[/color]=[color=#ba2121]"en"[/color][color=#008000][b]>[/b][/color]
  [color=#008000][b]<head>[/b][/color]
    [color=#008000][b]<meta[/b][/color] [color=#b00040]charset[/color]=[color=#ba2121]"utf-8"[/color] [color=#008000][b]/>[/b][/color]
    [color=#008000][b]<title>[/b][/color]Canvas[color=#008000][b]</title>[/b][/color]
  [color=#008000][b]</head>[/b][/color]

  [color=#008000][b]<body[/b][/color] [color=#b00040]onload[/color]=[color=#ba2121]"main()"[/color][color=#008000][b]>[/b][/color]
    [color=#008000][b]<canvas[/b][/color] [color=#b00040]id[/color]=[color=#ba2121]"example1"[/color] [color=#b00040]width[/color]=[color=#ba2121]"400"[/color] [color=#b00040]height[/color]=[color=#ba2121]"400"[/color][color=#008000][b]>[/b][/color]
      Please use a browser that supports [color=#ba2121]"canvas"[/color]
    [color=#008000][b]</canvas>[/b][/color]
    [color=#408080][i]<!-- 加载 WebGL 工具库 -->[/i][/color]
    [color=#008000][b]<script[/b][/color] [color=#b00040]src[/color]=[color=#ba2121]"./lib/webgl-utils.js"[/color][color=#008000][b]></script>[/b][/color]
    [color=#008000][b]<script[/b][/color] [color=#b00040]src[/color]=[color=#ba2121]"./lib/webgl-debug.js"[/color][color=#008000][b]></script>[/b][/color]
    [color=#008000][b]<script[/b][/color] [color=#b00040]src[/color]=[color=#ba2121]"./lib/cuon-utils.js"[/color][color=#008000][b]></script>[/b][/color]

    [color=#008000][b]<script>[/b][/color]
      [color=#008000][b]function[/b][/color] [color=#555555]main[/color][color=#555555]()[/color]
      [color=#555555]{[/color]
        [color=#008000][b]var[/b][/color] canvas [color=#555555]=[/color] document[color=#555555].[/color][color=#555555]getElementById[/color][color=#555555]([/color][color=#ba2121]'example1'[/color][color=#555555]);[/color]

        [color=#408080][i]// 获取 WebGL 渲染环境[/i][/color]
        [color=#008000][b]var[/b][/color] gl [color=#555555]=[/color] [color=#555555]getWebGLContext[/color][color=#555555]([/color]canvas[color=#555555]);[/color]

        [color=#408080][i]// 设置清屏颜色[/i][/color]
        gl[color=#555555].[/color][color=#555555]clearColor[/color][color=#555555]([/color][color=#666666]0.0[/color][color=#555555],[/color] [color=#666666]0.0[/color][color=#555555],[/color] [color=#666666]0.0[/color][color=#555555],[/color] [color=#666666]1.0[/color][color=#555555]);[/color]

        [color=#408080][i]// 刷新颜色缓冲区[/i][/color]
        gl[color=#555555].[/color][color=#555555]clear[/color][color=#555555]([/color]gl[color=#555555].[/color]COLOR_BUFFER_BIT[color=#555555]);[/color]
      [color=#555555]}[/color]
    [color=#008000][b]</script>[/b][/color]
  [color=#008000][b]</body>[/b][/color]
[color=#008000][b]</html>[/b][/color][/size][/font][/size][/font][/b][/td][/tr][/table][/list][/list]
在线示例:
[url]http://runjs.cn/code/xvrr2zpv[/url]
[/list][/list]

WebGL工具库:
[attach]10725[/attach]

523066680 发表于 2017-7-8 17:18

HTML JS 分离,从 顶点着色器确定一个点的位置,并着色。[code]<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>WebGL</title>
  </head>

  <body onload="main()">
    <canvas id="example1" width="400" height="400">
      Please use a browser that supports "canvas"
    </canvas>
    <script src="./lib/webgl-utils.js"></script>
    <script src="./lib/webgl-debug.js"></script>
    <script src="./lib/cuon-utils.js"></script>
    <script src="./example1.js"></script>
  </body>
</html>
[/code][code]function main()
{
    // Vertex shader program 顶点着色器
    var VSHADER_SOURCE =
        'void main() {\n' +
        '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // 设置图元的顶点坐标
        '  gl_PointSize = 10.0;\n' +                    // 设置点的大小
        '}\n';

    // Fragment shader program  片元着色器
    var FSHADER_SOURCE =
        'void main() {\n' +
        '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // 颜色
        '}\n';

    var canvas = document.getElementById('example1');

    // 获取 WebGL 环境
    var gl = getWebGLContext(canvas);

    // 初始化着色器
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
    {
        console.log('Failed to intialize shaders.');
        return;
    }
   
    //设置并清除颜色缓冲区
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.drawArrays(gl.Points, 0, 1);
}
[/code]

happy886rr 发表于 2017-7-8 17:44

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=201083&ptid=44672]2#[/url] [i]523066680[/i] [/b]
我也觉得前端很好玩,打算放弃C语言,转学前端。

523066680 发表于 2017-7-8 17:49

[i=s] 本帖最后由 523066680 于 2017-7-8 17:55 编辑 [/i]

[b]回复 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=201085&ptid=44672]3#[/url] [i]happy886rr[/i] [/b]

    C/C++属于终身技能,说"放弃",言重了。只是临时换口味。而且 js 还是类C语言,花括号分号一样一样的。

523066680 发表于 2017-7-8 19:15

[i=s] 本帖最后由 523066680 于 2017-7-8 19:29 编辑 [/i]

昨天把自己那个1024特效用shader完成了,用WebGL是为了方便学习和实践,本质上我还是在用纯C作为主程序,希望能一直用下去。

实时动态渲染
[img]http://imgout.ph.126.net/56565042/v.jpg[/img][code]#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <time.h>

#define SIZE_X 500
#define SIZE_Y 500

int winID;
int program;

GLuint vTest;
GLfloat test = 200.0;

GLuint vAng;
GLfloat ang = 0.0;

const GLchar* readShader( const char *filename );

void display(void)
{
    static const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    glClearBufferfv(GL_COLOR, 0, black );

    glDrawArrays(GL_POINTS, 0, 1);
    glutSwapBuffers();
}

void idle(void)
{
    usleep(10000);
    ang += 0.05;
    glVertexAttrib1f( vAng, ang );

    glutPostRedisplay();
}

void reshape(int Width,int Height)
{
    glViewport(0, 0, Width, Height);     //视口范围
}

void keypress(unsigned char key, int mousex, int mousey)
{
    switch (key)
    {
        case 'q':
            glutDestroyWindow(winID);
            exit(0);
            break;
        case 'Q':
            glutDestroyWindow(winID);
            exit(0);
            break;
        case ']':
            test += test*0.1;
            glVertexAttrib1f( vTest, test );
            glutPostRedisplay();
            break;
        case '[':
            test -= test*0.1;
            glVertexAttrib1f( vTest, test );
            glutPostRedisplay();
            break;
    }
}

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    //允许修改点元素大小
    glEnable(GL_PROGRAM_POINT_SIZE);

    srand(time(NULL));
}

int loadShader(void)
{

    // Very Important !
    glewInit();
    const GLchar * vs_src;
    const GLchar * fs_src;

    vs_src = readShader( "pointTest.vert" );
    fs_src = readShader( "pointTest.frag" );

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, &vs_src, NULL);
    glCompileShader(vs);

    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fs, 1, &fs_src, NULL);
    glCompileShader(fs);

    program = glCreateProgram();

    glAttachShader(program, vs);
    glAttachShader(program, fs);

    glLinkProgram(program);

    glUseProgram(program);

    vTest = glGetAttribLocation( program, "vTest" );
    glVertexAttrib1f( vTest, test );
    printf("%d\n", vTest);

    vAng = glGetAttribLocation( program, "vAng" );
    glVertexAttrib1f( vAng, ang );

}

int main(int argc, char *argv[])
{

    glutInit(&argc, argv);
            //显示模式   双缓冲         RGBA  
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(SIZE_X, SIZE_Y);       //窗口大小
    glutInitWindowPosition(10, 10);         //位置
    winID = glutCreateWindow("Simple");  //窗口句柄

    init();
    loadShader();

    glutDisplayFunc(display);          //显示
    glutKeyboardFunc(keypress);        //按键事件响应
    glutReshapeFunc(reshape);          //窗口事件响应
    glutIdleFunc(idle);                //闲时回调函数
    glutMainLoop();                    //开始主循环
    return 0;
}


const GLchar* readShader( const char *filename )
{
    FILE *FILE = fopen(filename, "rb");

    GLchar *source;
    int size;

    fseek( FILE, 0, SEEK_END  );
    size = ftell(FILE) + 1;
    fseek( FILE, 0, SEEK_SET  );  //turn back

    source = (GLchar *) malloc( sizeof(GLchar) * size );
    fread( source, 1, size, FILE);

    return (const GLchar*)(source);  //强制转换
}[/code]Vertex Shader[code]#version 420 core

attribute float vTest;
attribute float vAng;

out vec4 coord;
out float fTest;
out float fAng;

void main(void)
{
    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
    gl_PointSize = 480.0;
    coord = gl_Position;
    fTest = vTest;
    fAng = vAng;
}

/*
    备注:attribute 只能在 顶点着色器中使用

    实际测试 如果 main 中没有用到 传入的变量
    主程序中就无法通过 GetAttribLocation 获取该变量索引。
*/
[/code]Fragment Sahder[code]#version 420 core

in float fTest;
in float fAng;

float RGB(float x, float y, float e)
{
    return ( x * tan(x/y) ) * ( y * tan( x/y + fAng*e ) ) / fTest;
}

void main(void)
{
    vec4 coord = (gl_FragCoord - 250.0)*2.0; //平移,并扩大两倍计算范围

    gl_FragColor =
        vec4(
            int(RGB(coord.x, coord.y, 0.33))%255/255.0,
            int(RGB(coord.x, coord.y, 0.66))%255/255.0,
            int(RGB(coord.x, coord.y, 0.99))%255/255.0,
            0.0
        );
}
[/code]编译脚本(实在记不住 makefile 语法,用批处理)[code]@echo off
set path=D:\tdm-gcc-64\bin

:Compile
gcc -std=c11 "%1" -o "%~n1.exe" ^
                   -ID:\Lib\freeglut-MinGW-3.0.0-1.mp\include  ^
                   -LD:\Lib\freeglut-MinGW-3.0.0-1.mp\lib\x64 ^
                   -ID:\Lib\glew-1.13.0\include ^
                   -LD:\Lib\glew-1.13.0\lib ^
                   -lfreeglut -lglew32 -lopengl32 -lglu32

:Run
if %errorlevel% == 0 (
        %~n1.exe
) else (
        echo Compile Error
        pause
)[/code]

523066680 发表于 2017-7-8 19:36

本帖不再更新,对于有兴趣的朋友,推荐:《WebGL Programming Guide》

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.