This function takes a description of a flat polygon in x, y and z coordinates, and draws it in three dimensions.

polygon3d(x, y = NULL, z = NULL, fill = TRUE, plot = TRUE,
coords = 1:2, random = TRUE, ...)

## Arguments

x, y, z

Vertices of the polygon in a form accepted by xyz.coords.

fill

logical; should the polygon be filled?

plot

logical; should the polygon be displayed?

coords

Which two coordinates (x = 1, y = 2, z = 3) describe the polygon.

random

Should a random triangulation be used?

...

Other parameters to pass to lines3d or shade3d if plot = TRUE.

## Details

The function triangulates the two dimensional polygon described by coords, then applies the triangulation to all three coordinates. No check is made that the polygon is actually all in one plane, but the results may be somewhat unpredictable (especially if random = TRUE) if it is not.

Polygons need not be simple; use NA to indicate separate closed pieces. For fill = FALSE there are no other restrictions on the pieces, but for fill = TRUE the resulting two-dimensional polygon needs to be one that triangulate can handle.

## Value

If plot = TRUE, the id number of the lines (for fill = FALSE) or triangles (for fill = TRUE) that have been plotted. If plot = FALSE, then for fill = FALSE, a vector of indices into the XYZ matrix that could be used to draw the polygon. For fill = TRUE, a triangular mesh object representing the triangulation.

## Author

Duncan Murdoch

extrude3d for a solid extrusion of a polygon, triangulate for the triangulation.

## Examples

theta <- seq(0, 4*pi, len = 50)
r <- theta + 1
r <- c(r[-50], rev(theta*0.8) + 1)
theta <- c(theta[-50], rev(theta))
x <- r*cos(theta)
y <- r*sin(theta)
open3d()
plot(x, y, type = "n")
polygon(x, y)

polygon3d(x, y, x + y, col = "blue")

{"x":{"material":{"color":"#000000","alpha":1,"lit":true,"ambient":"#000000","specular":"#FFFFFF","emission":"#000000","shininess":50,"smooth":true,"front":"filled","back":"filled","size":3,"lwd":1,"fog":true,"point_antialias":false,"line_antialias":false,"texture":null,"textype":"rgb","texmipmap":false,"texminfilter":"linear","texmagfilter":"linear","texenvmap":false,"depth_mask":true,"depth_test":"less","isTransparent":false,"polygon_offset":[0,0],"margin":"","floating":false,"tag":""},"rootSubscene":1379,"objects":{"1385":{"id":1385,"type":"triangles","material":{},"vertices":"0","colors":"2","centers":"3","normals":"1","ignoreExtent":false,"flags":32771},"1383":{"id":1383,"type":"light","vertices":[[0,0,1]],"colors":[[1,1,1,1],[1,1,1,1],[1,1,1,1]],"viewpoint":true,"finite":false},"1382":{"id":1382,"type":"background","material":{},"colors":"4","centers":"5","sphere":false,"fogtype":"none","fogscale":1,"flags":32768},"1384":{"id":1384,"type":"background","material":{"lit":false,"back":"lines"},"colors":"6","centers":"7","sphere":false,"fogtype":"none","fogscale":1,"flags":32768},"1379":{"id":1379,"type":"subscene","par3d":{"antialias":8,"FOV":30,"ignoreExtent":false,"listeners":1379,"mouseMode":{"none":"none","left":"trackball","right":"zoom","middle":"fov","wheel":"pull"},"observer":[0,0,80.4372482299805],"modelMatrix":[[1,0,0,-1.20363521575928],[0,0.342020153999329,0.939692616462708,2.60269904136658],[0,-0.939692616462708,0.342020153999329,-81.1461563110352],[0,0,0,1]],"projMatrix":[[3.73205089569092,0,0,0],[0,3.73205089569092,0,0],[0,0,-3.86370372772217,-289.967010498047],[0,0,-1,0]],"skipRedraw":false,"userMatrix":[[1,0,0,0],[0,0.342020143325668,0.939692620785909,0],[0,-0.939692620785909,0.342020143325668,0],[0,0,0,1]],"userProjection":[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],"scale":[1,1,1],"viewport":{"x":0,"y":0,"width":1,"height":1},"zoom":1,"bbox":[-10.4673414230347,12.8746118545532,-12.0214519500732,8.90879535675049,-15.9031829833984,11.4966287612915],"windowRect":[274,324,530,580],"family":"sans","font":1,"cex":1,"useFreeType":true,"fontname":"/System/Library/Fonts/Supplemental/Arial.ttf","maxClipPlanes":6,"glVersion":2.1,"activeSubscene":0},"embeddings":{"viewport":"replace","projection":"replace","model":"replace","mouse":"replace"},"objects":[1384,1385,1383],"subscenes":[],"flags":33027}},"crosstalk":{"key":[],"group":[],"id":[],"options":[]},"width":480,"height":480,"buffer":{"accessors":[{"bufferView":0,"componentType":5126,"count":291,"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":291,"type":"VEC3"},{"bufferView":2,"componentType":5121,"count":1,"type":"VEC4"},{"bufferView":3,"componentType":5126,"count":97,"type":"VEC3"},{"bufferView":4,"componentType":5126,"count":1,"type":"VEC4"},{"bufferView":5,"componentType":5121,"count":1,"type":"VEC3"},{"bufferView":6,"componentType":5121,"count":1,"type":"VEC4"},{"bufferView":7,"componentType":5121,"count":1,"type":"VEC3"}],"bufferViews":[{"buffer":0,"byteLength":3492,"byteOffset":0},{"buffer":0,"byteLength":3492,"byteOffset":3492},{"buffer":0,"byteLength":4,"byteOffset":6984},{"buffer":0,"byteLength":1164,"byteOffset":6988},{"buffer":0,"byteLength":16,"byteOffset":8152},{"buffer":0,"byteLength":3,"byteOffset":8168},{"buffer":0,"byteLength":4,"byteOffset":8171},{"buffer":0,"byteLength":3,"byteOffset":8175}],"buffers":[{"byteLength":8178,"bytes":"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\nNM0TvzrNE79BzRM/NM0TvzrNE79BzRM/NM0TvzrNE79BzRM/H80TvyPNE79vzRM/H80TvyPN\nE79vzRM/H80TvyPNE79vzRM/OM0TvzvNE789zRM/OM0TvzvNE789zRM/OM0TvzvNE789zRM/\nOc0TvznNE789zRM/Oc0TvznNE789zRM/Oc0TvznNE789zRM/QM0TvyXNE79JzRM/QM0TvyXN\nE79JzRM/QM0TvyXNE79JzRM/O80Tvz7NE782zRM/O80Tvz7NE782zRM/O80Tvz7NE782zRM/\nO80TvzzNE785zRM/O80TvzzNE785zRM/O80TvzzNE785zRM/Oc0Tvz3NE786zRM/Oc0Tvz3N\nE786zRM/Oc0Tvz3NE786zRM/OM0TvzvNE787zRM/OM0TvzvNE787zRM/OM0TvzvNE787zRM/\nO80TvznNE785zRM/O80TvznNE785zRM/O80TvznNE785zRM/O80TvzvNE786zRM/O80TvzvN\nE786zRM/O80TvzvNE786zRM/O80TvzrNE786zRM/O80TvzrNE786zRM/O80TvzrNE786zRM/\nOc0TvzrNE785zRM/Oc0TvzrNE785zRM/Oc0TvzrNE785zRM/Oc0TvzvNE787zRM/Oc0TvzvN\nE787zRM/Oc0TvzvNE787zRM/QM0TvzbNE785zRM/QM0TvzbNE785zRM/QM0TvzbNE785zRM/\nPM0TvznNE784zRM/PM0TvznNE784zRM/PM0TvznNE784zRM/PM0Tvz3NE78yzRM/PM0Tvz3N\nE78yzRM/PM0Tvz3NE78yzRM/Os0TvzrNE786zRM/Os0TvzrNE786zRM/Os0TvzrNE786zRM/\nOc0TvzrNE787zRM/Oc0TvzrNE787zRM/Oc0TvzrNE787zRM/PM0TvzfNE788zRM/PM0TvzfN\nE788zRM/PM0TvzfNE788zRM/Os0TvznNE786zRM/Os0TvznNE786zRM/Os0TvznNE786zRM/\nOs0TvznNE786zRM/Os0TvznNE786zRM/Os0TvznNE786zRM/Os0TvzrNE786zRM/Os0TvzrN\nE786zRM/Os0TvzrNE786zRM/O80TvznNE787zRM/O80TvznNE787zRM/O80TvznNE787zRM/\nK80Tv0zNE784zRM/K80Tv0zNE784zRM/K80Tv0zNE784zRM/Ns0Tvz3NE785zRM/Ns0Tvz3N\nE785zRM/Ns0Tvz3NE785zRM/Oc0TvzzNE786zRM/Oc0TvzzNE786zRM/Oc0TvzzNE786zRM/\nOc0TvzvNE786zRM/Oc0TvzvNE786zRM/Oc0TvzvNE786zRM/Ns0TvzvNE788zRM/Ns0TvzvN\nE788zRM/Ns0TvzvNE788zRM/PM0TvzvNE787zRM/PM0TvzvNE787zRM/PM0TvzvNE787zRM/\nMM0Tv0DNE78/zRM/MM0Tv0DNE78/zRM/MM0Tv0DNE78/zRM/PM0TvzjNE786zRM/PM0TvzjN\nE786zRM/PM0TvzjNE786zRM/PM0TvzjNE786zRM/PM0TvzjNE786zRM/PM0TvzjNE786zRM/\nO80TvzzNE784zRM/O80TvzzNE784zRM/O80TvzzNE784zRM/NM0TvzfNE79DzRM/NM0TvzfN\nE79DzRM/NM0TvzfNE79DzRM/PM0TvznNE784zRM/PM0TvznNE784zRM/PM0TvznNE784zRM/\nN80Tvz3NE786zRM/N80Tvz3NE786zRM/N80Tvz3NE786zRM/Pc0TvzjNE786zRM/Pc0TvzjN\nE786zRM/Pc0TvzjNE786zRM/Os0TvzrNE786zRM/Os0TvzrNE786zRM/Os0TvzrNE786zRM/\nOs0TvzvNE785zRM/Os0TvzvNE785zRM/Os0TvzvNE785zRM/Oc0TvzvNE785zRM/Oc0TvzvN\nE785zRM/Oc0TvzvNE785zRM/M80Tvz/NE787zRM/M80Tvz/NE787zRM/M80Tvz/NE787zRM/\nO80TvznNE787zRM/O80TvznNE787zRM/O80TvznNE787zRM/N80Tvz7NE786zRM/N80Tvz7N\nE786zRM/N80Tvz7NE786zRM/OM0TvznNE789zRM/OM0TvznNE789zRM/OM0TvznNE789zRM/\nQM0TvzrNE782zRM/QM0TvzrNE782zRM/QM0TvzrNE782zRM/Os0TvzrNE786zRM/Os0TvzrN\nE786zRM/Os0TvzrNE786zRM/P80TvzfNE784zRM/P80TvzfNE784zRM/P80TvzfNE784zRM/\nOs0TvzzNE784zRM/Os0TvzzNE784zRM/Os0TvzzNE784zRM/PM0TvzvNE786zRM/PM0TvzvN\nE786zRM/PM0TvzvNE786zRM/PM0TvzrNE785zRM/PM0TvzrNE785zRM/PM0TvzrNE785zRM/\nN80TvzzNE784zRM/N80TvzzNE784zRM/N80TvzzNE784zRM/PM0TvzfNE788zRM/PM0TvzfN\nE788zRM/PM0TvzfNE788zRM/Ps0TvzLNE79AzRM/Ps0TvzLNE79AzRM/Ps0TvzLNE79AzRM/\nO80TvzvNE785zRM/O80TvzvNE785zRM/O80TvzvNE785zRM/O80TvzrNE786zRM/O80TvzrN\nE786zRM/O80TvzrNE786zRM/Oc0TvznNE787zRM/Oc0TvznNE787zRM/Oc0TvznNE787zRM/\nO80TvzjNE788zRM/O80TvzjNE788zRM/O80TvzjNE788zRM/O80TvzvNE787zRM/O80TvzvN\nE787zRM/O80TvzvNE787zRM/Os0TvzzNE786zRM/Os0TvzzNE786zRM/Os0TvzzNE786zRM/\nPs0TvzTNE787zRM/Ps0TvzTNE787zRM/Ps0TvzTNE787zRM/OM0TvzvNE787zRM/OM0TvzvN\nE787zRM/OM0TvzvNE787zRM/OM0Tvz3NE788zRM/OM0Tvz3NE788zRM/OM0Tvz3NE788zRM/\nOc0TvzzNE785zRM/Oc0TvzzNE785zRM/Oc0TvzzNE785zRM/O80TvzrNE786zRM/O80TvzrN\nE786zRM/O80TvzrNE786zRM/Oc0Tvz3NE786zRM/Oc0Tvz3NE786zRM/Oc0Tvz3NE786zRM/\nOc0TvzrNE787zRM/Oc0TvzrNE787zRM/Oc0TvzrNE787zRM/Oc0TvzrNE786zRM/Oc0TvzrN\nE786zRM/Oc0TvzrNE786zRM/Ps0TvzzNE781zRM/Ps0TvzzNE781zRM/Ps0TvzzNE781zRM/\nMs0Tv0PNE787zRM/Ms0Tv0PNE787zRM/Ms0Tv0PNE787zRM/Os0TvzrNE787zRM/Os0TvzrN\nE787zRM/Os0TvzrNE787zRM/Pc0Tvz3NE781zRM/Pc0Tvz3NE781zRM/Pc0Tvz3NE781zRM/\nO80TvzvNE787zRM/O80TvzvNE787zRM/O80TvzvNE787zRM/N80Tv0HNE782zRM/N80Tv0HN\nE782zRM/N80Tv0HNE782zRM/N80Tvz7NE787zRM/N80Tvz7NE787zRM/N80Tvz7NE787zRM/\nOM0Tvz7NE782zRM/OM0Tvz7NE782zRM/OM0Tvz7NE782zRM/Os0TvzrNE786zRM/Os0TvzrN\nE786zRM/Os0TvzrNE786zRM/P80TvzTNE78+zRM/P80TvzTNE78+zRM/P80TvzTNE78+zRM/\nPs0TvzjNE783zRM/Ps0TvzjNE783zRM/Ps0TvzjNE783zRM/Os0TvzjNE78+zRM/Os0TvzjN\nE78+zRM/Os0TvzjNE78+zRM/O80TvzvNE786zRM/O80TvzvNE786zRM/O80TvzvNE786zRM/\nNM0Tvz7NE78+zRM/NM0Tvz7NE78+zRM/NM0Tvz7NE78+zRM/R80TvzTNE780zRM/R80TvzTN\nE780zRM/R80TvzTNE780zRM/M80Tv0bNE782zRM/M80Tv0bNE782zRM/M80Tv0bNE782zRM/\nOc0TvzvNE787zRM/Oc0TvzvNE787zRM/Oc0TvzvNE787zRM/O80Tv0LNE78yzRM/O80Tv0LN\nE78yzRM/O80Tv0LNE78yzRM/Nc0Tvz/NE787zRM/Nc0Tvz/NE787zRM/Nc0Tvz/NE787zRM/\nQs0TvzfNE783zRM/Qs0TvzfNE783zRM/Qs0TvzfNE783zRM/R80TvzLNE780zRM/R80TvzLN\nE780zRM/R80TvzLNE780zRM/NM0Tv0DNE787zRM/NM0Tv0DNE787zRM/NM0Tv0DNE787zRM/\nN80Tvz7NE786zRM/N80Tvz7NE786zRM/N80Tvz7NE786zRM/OM0TvzvNE788zRM/OM0TvzvN\nE788zRM/OM0TvzvNE788zRM/AAABAW8Shz8ysNA9ch2UP8hCkD8OIVU+6+aqP2gGmj+yreA+\n1DHSP0yEnj+uSj8/oin+P+0snD/m/4E/ahYPQKMDkD9i5qY/A3UbQLQvbj+Oz8k/s3MgQHYP\nVT8KvOQ/4qEnQCZn3T58rQdAYVojQOa7a7409xdAdjsJQP+aIL8p9RtA05znP+d6h7+OWB5A\nMza1P28Awr+LoRhAToVeP2D/+r8oMApAewdLPiMJIsBw1+0/q3Usv9/cRcCIMKY/N4nlv2sB\nWcDYPlE/tbEkwCvbY8BYaXc+lmRUwPRhcsDkEP6+CBKJwNxyb8ALk7q/MF6mwOfkZMAluAbA\nhs61wGy8TsBWzy3A4kW+wIb9M8CbumDAEFzKwHqm+b9OC4jA7HTGwC9WpL+OZ5TAGn29wCa0\nAb+iDpvAJ0WrwAZMNL2qEafAQnqowJp7oT86MaPAqKR1wD6sBkCn4pvAEBkxwC8EY0AGuYXA\na7chv7OklkC2HlbAZlWuP6rhq0DQXCvAg2YsQDtru0CfV+q/U9WAQJO3w0Cgq1q/H2KoQI7J\nyEC8a3o/BBfoQH41w0AAiyhAf70LQTNFukCQQ2tAfvMXQXp/qEAYhpRAyIIeQcvKfkDeWMZA\nIt8iQU9TM0Dbk9dAwp4YQXrz4z/6q+pAbNQRQYqJGz/SB/VAgjwEQX7dJL+Ya/VA6s/gQCmj\nDcASEPpAfj6zQOIJhcCgf+JAfOs6QJTyqcAX6s1ACt6PP9olycDHy69Al9BKv56A88Bog41A\nbPpLwObGCMFLphdAprrFwCoxD8FEXoA/w0r+wLbQD8EDKum+BhoXwRtEE8FacRHAcqA3wSLv\nBcEh95HAsupOwf7X9MALGb3AhPhYwVsv3cALnfXAM2ZpwbhEqcD1TAfBUu9bwQAlfMC49BTB\n+P1TwdeOGMBLzxzBAPNCwcQ//j7x/yPB8w0cwWZETkAK0iDB4IHawCZbnEBqIRvBreeZwE4+\n90BvBgrBeHRmv0jwAEFjHe/AXhkWP9NBxz8Lcy7B0IoVwfxdaL4Ohx5ALgEQQJr7hkDp04PA\nNuzJPQsbFkGvfMnAz3JFQHpmfMDurjO+tNCDwKIUJkFjYpnA4sayQH/C00DoitY/nLIEQRN9\nWkCKd53ABOTAv/xzTsBq0ljAM6PTwKvbHUCo367ApuM/wB99fT9Lyds/7EMtQPpbEEGW1grB\neKywPoTyiEDyUtJAu6ItQWCCNMD/z4PALxHewCD+974TH6/A9p6+wNOUJr+v/ClAelcAQLRJ\nOUFKsIXAHuPsQLjfvb/mdTLB3DFKweZ20L/yrQZBKD7ZQIBE1z6TIDzBcGY1wSTlhMB4XFq/\ntDCgwNfl68Av6ALBGtt4wVq220BmwVW+TgjVQKshHcGHix7AjMREwX/p5UBWWHg/RXoCQTOq\nScDv/AZBwySpQLvrGsAopgdAnyyavshFU0AIEPJAd9ktQZ9gAsFW0pVAzt1dwAzII8HoXTO/\n6v0uwZZUoj9YlkM/4Q8CQH+Q6MCWKcRAoJuRv1OKPMAu1O4/d0CKv/KTN0GuuQLAhuUWQZmY\nmD6ZmJg+mZiYPgAAgD8AAAABAQEBAAAA"}]},"context":{"shiny":false,"rmarkdown":null},"vertexShader":"#line 2 1\n// File 1 is the vertex shader\n#ifdef GL_ES\n#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\n#endif\n\nattribute vec3 aPos;\nattribute vec4 aCol;\nuniform mat4 mvMatrix;\nuniform mat4 prMatrix;\nvarying vec4 vCol;\nvarying vec4 vPosition;\n\n#ifdef NEEDS_VNORMAL\nattribute vec3 aNorm;\nuniform mat4 normMatrix;\nvarying vec4 vNormal;\n#endif\n\n#if defined(HAS_TEXTURE) || defined (IS_TEXT)\nattribute vec2 aTexcoord;\nvarying vec2 vTexcoord;\n#endif\n\n#ifdef FIXED_SIZE\nuniform vec3 textScale;\n#endif\n\n#ifdef FIXED_QUADS\nattribute vec3 aOfs;\n#endif\n\n#ifdef IS_TWOSIDED\n#ifdef HAS_NORMALS\nvarying float normz;\nuniform mat4 invPrMatrix;\n#else\nattribute vec3 aPos1;\nattribute vec3 aPos2;\nvarying float normz;\n#endif\n#endif // IS_TWOSIDED\n\n#ifdef FAT_LINES\nattribute vec3 aNext;\nattribute vec2 aPoint;\nvarying vec2 vPoint;\nvarying float vLength;\nuniform float uAspect;\nuniform float uLwd;\n#endif\n\n\nvoid main(void) {\n  \n#ifndef IS_BRUSH\n#if defined(NCLIPPLANES) || !defined(FIXED_QUADS) || defined(HAS_FOG)\n  vPosition = mvMatrix * vec4(aPos, 1.);\n#endif\n  \n#ifndef FIXED_QUADS\n  gl_Position = prMatrix * vPosition;\n#endif\n#endif // !IS_BRUSH\n  \n#ifdef IS_POINTS\n  gl_PointSize = POINTSIZE;\n#endif\n  \n  vCol = aCol;\n  \n#ifdef NEEDS_VNORMAL\n  vNormal = normMatrix * vec4(-aNorm, dot(aNorm, aPos));\n#endif\n  \n#ifdef IS_TWOSIDED\n#ifdef HAS_NORMALS\n  /* normz should be calculated *after* projection */\n  normz = (invPrMatrix*vNormal).z;\n#else\n  vec4 pos1 = prMatrix*(mvMatrix*vec4(aPos1, 1.));\n  pos1 = pos1/pos1.w - gl_Position/gl_Position.w;\n  vec4 pos2 = prMatrix*(mvMatrix*vec4(aPos2, 1.));\n  pos2 = pos2/pos2.w - gl_Position/gl_Position.w;\n  normz = pos1.x*pos2.y - pos1.y*pos2.x;\n#endif\n#endif // IS_TWOSIDED\n  \n#ifdef NEEDS_VNORMAL\n  vNormal = vec4(normalize(vNormal.xyz/vNormal.w), 1);\n#endif\n  \n#if defined(HAS_TEXTURE) || defined(IS_TEXT)\n  vTexcoord = aTexcoord;\n#endif\n  \n#if defined(FIXED_SIZE) && !defined(ROTATING)\n  vec4 pos = prMatrix * mvMatrix * vec4(aPos, 1.);\n  pos = pos/pos.w;\n  gl_Position = pos + vec4(aOfs*textScale, 0.);\n#endif\n  \n#if defined(IS_SPRITES) && !defined(FIXED_SIZE)\n  vec4 pos = mvMatrix * vec4(aPos, 1.);\n  pos = pos/pos.w + vec4(aOfs,  0.);\n  gl_Position = prMatrix*pos;\n#endif\n  \n#ifdef FAT_LINES\n  /* This code was inspired by Matt Deslauriers' code in \n   https://mattdesl.svbtle.com/drawing-lines-is-hard */\n  vec2 aspectVec = vec2(uAspect, 1.0);\n  mat4 projViewModel = prMatrix * mvMatrix;\n  vec4 currentProjected = projViewModel * vec4(aPos, 1.0);\n  currentProjected = currentProjected/currentProjected.w;\n  vec4 nextProjected = projViewModel * vec4(aNext, 1.0);\n  vec2 currentScreen = currentProjected.xy * aspectVec;\n  vec2 nextScreen = (nextProjected.xy / nextProjected.w) * aspectVec;\n  float len = uLwd;\n  vec2 dir = vec2(1.0, 0.0);\n  vPoint = aPoint;\n  vLength = length(nextScreen - currentScreen)/2.0;\n  vLength = vLength/(vLength + len);\n  if (vLength > 0.0) {\n    dir = normalize(nextScreen - currentScreen);\n  }\n  vec2 normal = vec2(-dir.y, dir.x);\n  dir.x /= uAspect;\n  normal.x /= uAspect;\n  vec4 offset = vec4(len*(normal*aPoint.x*aPoint.y - dir), 0.0, 0.0);\n  gl_Position = currentProjected + offset;\n#endif\n  \n#ifdef IS_BRUSH\n  gl_Position = vec4(aPos, 1.);\n#endif\n}","fragmentShader":"#line 2 2\n// File 2 is the fragment shader\n#ifdef GL_ES\n#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\n#endif\nvarying vec4 vCol; // carries alpha\nvarying vec4 vPosition;\n#if defined(HAS_TEXTURE) || defined (IS_TEXT)\nvarying vec2 vTexcoord;\nuniform sampler2D uSampler;\n#endif\n\n#ifdef HAS_FOG\nuniform int uFogMode;\nuniform vec3 uFogColor;\nuniform vec4 uFogParms;\n#endif\n\n#if defined(IS_LIT) && !defined(FIXED_QUADS)\nvarying vec4 vNormal;\n#endif\n\n#if NCLIPPLANES > 0\nuniform vec4 vClipplane[NCLIPPLANES];\n#endif\n\n#if NLIGHTS > 0\nuniform mat4 mvMatrix;\n#endif\n\n#ifdef IS_LIT\nuniform vec3 emission;\nuniform float shininess;\n#if NLIGHTS > 0\nuniform vec3 ambient[NLIGHTS];\nuniform vec3 specular[NLIGHTS]; // light*material\nuniform vec3 diffuse[NLIGHTS];\nuniform vec3 lightDir[NLIGHTS];\nuniform bool viewpoint[NLIGHTS];\nuniform bool finite[NLIGHTS];\n#endif\n#endif // IS_LIT\n\n#ifdef IS_TWOSIDED\nuniform bool front;\nvarying float normz;\n#endif\n\n#ifdef FAT_LINES\nvarying vec2 vPoint;\nvarying float vLength;\n#endif\n\nvoid main(void) {\n  vec4 fragColor;\n#ifdef FAT_LINES\n  vec2 point = vPoint;\n  bool neg = point.y < 0.0;\n  point.y = neg ? (point.y + vLength)/(1.0 - vLength) :\n                 -(point.y - vLength)/(1.0 - vLength);\n#if defined(IS_TRANSPARENT) && defined(IS_LINESTRIP)\n  if (neg && length(point) <= 1.0) discard;\n#endif\n  point.y = min(point.y, 0.0);\n  if (length(point) > 1.0) discard;\n#endif // FAT_LINES\n  \n#ifdef ROUND_POINTS\n  vec2 coord = gl_PointCoord - vec2(0.5);\n  if (length(coord) > 0.5) discard;\n#endif\n  \n#if NCLIPPLANES > 0\n  for (int i = 0; i < NCLIPPLANES; i++)\n    if (dot(vPosition, vClipplane[i]) < 0.0) discard;\n#endif\n    \n#ifdef FIXED_QUADS\n    vec3 n = vec3(0., 0., 1.);\n#elif defined(IS_LIT)\n    vec3 n = normalize(vNormal.xyz);\n#endif\n    \n#ifdef IS_TWOSIDED\n    if ((normz <= 0.) != front) discard;\n#endif\n    \n#ifdef IS_LIT\n    vec3 eye = normalize(-vPosition.xyz/vPosition.w);\n    vec3 lightdir;\n    vec4 colDiff;\n    vec3 halfVec;\n    vec4 lighteffect = vec4(emission, 0.);\n    vec3 col;\n    float nDotL;\n#ifdef FIXED_QUADS\n    n = -faceforward(n, n, eye);\n#endif\n    \n#if NLIGHTS > 0\n    for (int i=0;i<NLIGHTS;i++) {\n      colDiff = vec4(vCol.rgb * diffuse[i], vCol.a);\n      lightdir = lightDir[i];\n      if (!viewpoint[i])\n        lightdir = (mvMatrix * vec4(lightdir, 1.)).xyz;\n      if (!finite[i]) {\n        halfVec = normalize(lightdir + eye);\n      } else {\n        lightdir = normalize(lightdir - vPosition.xyz/vPosition.w);\n        halfVec = normalize(lightdir + eye);\n      }\n      col = ambient[i];\n      nDotL = dot(n, lightdir);\n      col = col + max(nDotL, 0.) * colDiff.rgb;\n      col = col + pow(max(dot(halfVec, n), 0.), shininess) * specular[i];\n      lighteffect = lighteffect + vec4(col, colDiff.a);\n    }\n#endif\n    \n#else // not IS_LIT\n    vec4 colDiff = vCol;\n    vec4 lighteffect = colDiff;\n#endif\n    \n#ifdef IS_TEXT\n    vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n#endif\n    \n#ifdef HAS_TEXTURE\n#ifdef TEXTURE_rgb\n    vec4 textureColor = lighteffect*vec4(texture2D(uSampler, vTexcoord).rgb, 1.);\n#endif\n    \n#ifdef TEXTURE_rgba\n    vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n#endif\n    \n#ifdef TEXTURE_alpha\n    vec4 textureColor = texture2D(uSampler, vTexcoord);\n    float luminance = dot(vec3(1.,1.,1.), textureColor.rgb)/3.;\n    textureColor =  vec4(lighteffect.rgb, lighteffect.a*luminance);\n#endif\n    \n#ifdef TEXTURE_luminance\n    vec4 textureColor = vec4(lighteffect.rgb*dot(texture2D(uSampler, vTexcoord).rgb, vec3(1.,1.,1.))/3., lighteffect.a);\n#endif\n    \n#ifdef TEXTURE_luminance_alpha\n    vec4 textureColor = texture2D(uSampler, vTexcoord);\n    float luminance = dot(vec3(1.,1.,1.),textureColor.rgb)/3.;\n    textureColor = vec4(lighteffect.rgb*luminance, lighteffect.a*textureColor.a);\n#endif\n    \n    fragColor = textureColor;\n\n#elif defined(IS_TEXT)\n    if (textureColor.a < 0.1)\n      discard;\n    else\n      fragColor = textureColor;\n#else\n    fragColor = lighteffect;\n#endif // HAS_TEXTURE\n    \n#ifdef HAS_FOG\n    // uFogParms elements: x = near, y = far, z = fogscale, w = (1-sin(FOV/2))/(1+sin(FOV/2))\n    // In Exp and Exp2: use density = density/far\n    // fogF will be the proportion of fog\n    // Initialize it to the linear value\n    float fogF;\n    if (uFogMode > 0) {\n      fogF = (uFogParms.y - vPosition.z/vPosition.w)/(uFogParms.y - uFogParms.x);\n      if (uFogMode > 1)\n        fogF = mix(uFogParms.w, 1.0, fogF);\n      fogF = fogF*uFogParms.z;\n      if (uFogMode == 2)\n        fogF = 1.0 - exp(-fogF);\n      // Docs are wrong: use (density*c)^2, not density*c^2\n      // https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/mesa/swrast/s_fog.c#L58\n      else if (uFogMode == 3)\n        fogF = 1.0 - exp(-fogF*fogF);\n      fogF = clamp(fogF, 0.0, 1.0);\n      gl_FragColor = vec4(mix(fragColor.rgb, uFogColor, fogF), fragColor.a);\n    } else gl_FragColor = fragColor;\n#else\n    gl_FragColor = fragColor;\n#endif // HAS_FOG\n    \n}","players":[],"webGLoptions":{"preserveDrawingBuffer":true}},"evals":[],"jsHooks":[]}