Commit 235c7353 authored by García-Hernández's avatar García-Hernández

Support geometry and TCS shaders

Add fullvalues option: ply filenames are listed explicitly, and do not
use the <timestep>-<iso> nomenclature.
Add cutplanes option with two parameters: nearcut, farcut.
Add CuttingPlane value to menubutton. If enabled, the button will
provide a cutting plane which moves smoothly between neacut and farcut
and back.
Support http(s) based config files.
Use two-faced normals in iso shader.
Send 'A' for selected atom in multiuser mode.
Add optional chain affiliations to atoms (chainfile option).
parent fdc640e9
/*
# Copyright 2016-2018 Ruben Jesus Garcia Hernandez
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/
#include "BondShaders.h"
const char * const BondShader [] = {"Bond Renderer",
//vertex
#if defined(WIN32) || defined(CAVE)
"#version 410\n"
#else
"#version 300 es\n"
#endif
"uniform mat4 matrix;\n"
"uniform float totalChains;\n"
"layout(location = 0) in vec3 pos;\n"
"layout(location = 1) in float atomIn;\n"
"layout(location = 2) in float chain;\n"
"out float c;\n"
"void main()\n"
"{\n"
"gl_Position = matrix * vec4(pos, 1);\n"
"if (totalChains<0.5)\n"
" c=atomIn;\n"
"else\n"
" c=chain;\n"
"}\n"
,
//fragment
#if defined(WIN32) || defined(CAVE)
"#version 410 core\n"
#else
"#version 300 es\n"
#endif
"in lowp vec4 color;\n"
"out highp vec4 outputColor;\n"
"void main()\n"
"{\n"
"outputColor = color;\n"
"}\n"
, //tess
nullptr
, //geometry
#if defined(WIN32) || defined(CAVE)
"#version 420 core\n"
#else
"#version 300 es\n"
#endif
"layout(binding=1) uniform sampler2D chainColours;\n"
"layout(binding=0) uniform sampler2D atomData;\n"
"uniform float totalChains;\n"
"uniform float totalatoms;\n"
"layout(lines) in;\n"
"layout(line_strip, max_vertices = 4) out;\n"
"in float c[];\n"
"out vec4 color;\n"
"vec4 GetColor (int v)\n"
"{"
" float coord;"
" if (totalChains >0.5) {\n"
" coord=c[v]/totalChains+0.5/totalChains;\n"
" return texture(chainColours, vec2(coord, 0));\n"
" } else {\n"
" coord=c[v]/totalatoms+0.5/totalatoms;\n"
" return texture(atomData, vec2(coord,0));\n"
" }\n"
"}"
"void main ()\n"
"{\n"
"float coord;\n"
"if (abs (c[0]-c[1]) < 0.1) {\n"
" gl_Position = gl_in[0].gl_Position;\n"
" color=GetColor(0);"
" EmitVertex();\n"
" gl_Position = gl_in[1].gl_Position;\n"
//" color=...;\n" //no change
" EmitVertex();\n"
" EndPrimitive();\n"
"} else {\n"
" gl_Position = gl_in[0].gl_Position;\n"
" color=GetColor(0);"
" EmitVertex();\n"
" gl_Position = (gl_in[0].gl_Position+gl_in[1].gl_Position)/2.0;\n"
//" color=...;\n" //no change
" EmitVertex();\n"
//" gl_Position = (gl_in[0].gl_Position+gl_in[1].gl_Position)/2.0;" //no change
" color=GetColor(1);"
" EmitVertex();\n"
" gl_Position = gl_in[1].gl_Position;\n"
//" color=texture(chainColours, vec2(coord, 0));\n" //no change
" EmitVertex();\n"
"}\n"
"EndPrimitive();\n"
"}\n",
//tess eval
nullptr
};
\ No newline at end of file
/*
# Copyright 2016-2018 Ruben Jesus Garcia Hernandez
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/
extern const char * const BondShader[];
\ No newline at end of file
......@@ -18,9 +18,10 @@
#include <stdio.h>
#include "MyGL.h"
#include "eprintf.h"
#include "CompileGLShader.h"
GLuint CompileGLShader( const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader,
const char *pchTessEvalShader /*= nullptr*/)
const char *pchTessEvalShader /*= nullptr*/, const char *pchGeometryShader /*= nullptr*/, const char *pchTCS)
{
GLuint unProgramID = glCreateProgram();
......@@ -67,7 +68,7 @@ GLuint CompileGLShader( const char *pchShaderName, const char *pchVertexShader,
glAttachShader( unProgramID, nSceneFragmentShader );
glDeleteShader( nSceneFragmentShader ); // the program hangs onto this once it's attached
//tess
//tess eval
if (pchTessEvalShader) {
#if defined (__APPLE__) && !defined (GL_TESS_EVALUATION_SHADER)
eprintf ("Tess Eval Shaders unsupported on IOS");
......@@ -94,6 +95,49 @@ GLuint CompileGLShader( const char *pchShaderName, const char *pchVertexShader,
glDeleteShader(nSceneTessShader); // the program hangs onto this once it's attached
#endif
}
if (pchGeometryShader) {
GLuint GeometryShader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(GeometryShader, 1, &pchGeometryShader, nullptr);
glCompileShader(GeometryShader);
GLint tShaderCompiled = GL_FALSE;
glGetShaderiv(GeometryShader, GL_COMPILE_STATUS, &tShaderCompiled);
if (tShaderCompiled != GL_TRUE)
{
eprintf("%s - Unable to compile geometry shader %d!\n", pchShaderName, GeometryShader);
GLchar mess[3000];
GLsizei le;
glGetShaderInfoLog(GeometryShader, 3000, &le, mess);
eprintf("error messages: %s", mess);
glDeleteProgram(unProgramID);
glDeleteShader(GeometryShader);
return 0;
}
glAttachShader(unProgramID, GeometryShader);
glDeleteShader(GeometryShader); // the program hangs onto this once it's attached
}
if (pchTCS) {
GLuint TCS = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(TCS, 1, &pchTCS, nullptr);
glCompileShader(TCS);
GLint tShaderCompiled = GL_FALSE;
glGetShaderiv(TCS, GL_COMPILE_STATUS, &tShaderCompiled);
if (tShaderCompiled != GL_TRUE)
{
eprintf("%s - Unable to compile tesselation control shader %d!\n", pchShaderName, TCS);
GLchar mess[3000];
GLsizei le;
glGetShaderInfoLog(TCS, 3000, &le, mess);
eprintf("error messages: %s", mess);
glDeleteProgram(unProgramID);
glDeleteShader(TCS);
return 0;
}
glAttachShader(unProgramID, TCS);
glDeleteShader(TCS); // the program hangs onto this once it's attached
}
glLinkProgram( unProgramID );
......
......@@ -21,6 +21,8 @@
#define SHADERVERTEX 1
#define SHADERFRAGMENT 2
#define SHADERTESSEVAL 3
#define SHADERGEOMETRY 4
#define SHADERTCS 5
//-----------------------------------------------------------------------------
// Purpose: Compiles a GL shader program and returns the handle. Returns 0 if
......@@ -28,5 +30,5 @@
//-----------------------------------------------------------------------------
GLuint CompileGLShader( const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader,
const char *pchTessEvalShader = nullptr);
const char *pchTessEvalShader = nullptr, const char *pchGeometryShader = nullptr, const char *pchTCS = nullptr);
......@@ -30,6 +30,7 @@ char * SCREENSHOT;
int ISOS;
float **isocolours; // [ISOS][4];
const char **plyfiles;
const char *** fullplyfiles;
float **translations;
float userpos[3];
float scaling;
......@@ -69,6 +70,7 @@ bool showcontrollers;
bool gazenavigation;
int transparencyquality;
float nearclip, farclip;
float nearcut, farcut;
//markers such as hole positions and electron positions
float ** markers;
......@@ -83,7 +85,7 @@ menubutton_t menubutton;
std::vector<information> info;
int secret;
char * server;
const char * server;
int port;
bool resetTimestepOnReload;
......@@ -111,12 +113,54 @@ const char * loadConfigFileErrors[] =
"Markercolours with no previous correct timesteps parameter", //-18
"Error reading atomcolour", // -19
"Error reading newatom", //-20
"Error reading chains", //-21
"Error loading xyz file, add 100 to see the error",//<-100
"Error loading cube file, add 200 to see the error",//<-200
"Error loading encyclopedia json file, add 300 to see the error",//<-300
"Error loading analytics json file, add 400 to see the error",//<-400
};
int readChains(const char *file)
{
int r;
FILE *f=fopen (file, "r");
if (f==nullptr)
return -1;
fscanf (f, "chains");
r=fscanf (f, "%d", &numChains);
if (r!=1)
return -2;
if (numChains==-1) {//use atom colours
fclose(f);
return 0;
}
chainColours=new float[(numChains+1)*4];
for (int i=0;i<4;i++)
chainColours[i]=bondscolours[i];
for (int c=1;c<=numChains;c++) {
for (int i=0;i<4;i++) {
r=fscanf (f, "%f", chainColours+c*4+i);
if (r!=1) {
fclose (f);
return -3;
}
}
}
r=fscanf (f, " affiliations");
atomAffiliations=new int[numAtoms[0]];
for (int i=0;i<numAtoms[0];i++) {
r=fscanf (f, "%d", atomAffiliations+i);
if (r!=1) {
fclose (f);
return -4;
}
}
fclose(f);
return 0;
}
void cleanMarkers()
{
for (int i=0;i<TIMESTEPS;i++)
......@@ -208,8 +252,19 @@ void cleanConfig()
for (int i=0;i<ISOS;i++)
free ((void*)(plyfiles[i])); //strdup
delete[] plyfiles;
plyfiles = nullptr;
}
plyfiles=nullptr;
if (fullplyfiles) {
for (int j = 0; j < TIMESTEPS; j++) {
for (int i = 0; i < ISOS; i++)
free((void*)(fullplyfiles[j][i])); //strdup
delete[] fullplyfiles[j];
}
delete[] fullplyfiles;
fullplyfiles = nullptr;
}
free(PATH);
PATH=nullptr;
atomtrajectoryrestarts.clear();
......@@ -237,10 +292,20 @@ void cleanConfig()
delete[] numAtoms;
numAtoms=nullptr;
atoms=nullptr;
delete[] atomAffiliations;
atomAffiliations=nullptr;
delete[] chainColours;
chainColours=nullptr;
}
delete[] server;
server=nullptr;
if (numChains!=0) {
delete[] chainColours;
numChains=0;
}
}
void initState()
......@@ -273,8 +338,8 @@ void initState()
markers=nullptr;
markercolours=nullptr;
displayunitcell=false;
scaling =1;
markerscaling=0.8;
scaling =1.0f;
markerscaling=0.8f;
for (int i=0;i<3;i++)
cubetrans[i]=0;
translations=nullptr;
......@@ -290,6 +355,8 @@ void initState()
transparencyquality=12;
nearclip=0.2f;
farclip=200.f;
nearcut = 0.2f;
farcut = 0.2f;
for (int i=0;i<4;i++)
unitcellcolour[i]=1.0f;
......@@ -323,6 +390,9 @@ void initState()
bondscaling = 0.7f;
bondThickness = 1.0f;
atomAffiliations=nullptr;
chainColours=nullptr;
secret=0;
server=nullptr;
port=-1;
......@@ -343,8 +413,7 @@ int loadConfigFile(const char * f)
FILE *F = fopen(f, "r");
if (F == 0)
{
eprintf( "Could not open config file %s\n", f);
eprintf("Error: %d", errno);
eprintf( "Could not open config file %s, error (errno) = %d\n", f, errno);
return -1;
}
char s[100];
......@@ -397,6 +466,23 @@ int loadConfigFile(const char * f)
}
}
else if (!strcmp(s, "fullvalues")) {
if (TIMESTEPS == 0 || ISOS == 0) {
eprintf("full values with no previous correct isos or timesteps parameter\n");
fclose(F);
return -3;
}
fullplyfiles = new const char **[TIMESTEPS];
for (int j = 0; j < TIMESTEPS; j++) {
for (int i = 0; i < ISOS; i++) {
r = readString(F, s);
if (r != 0)
return -14;
free((void*)(fullplyfiles[j][i]));
fullplyfiles[j][i] = strdup(s);
}
}
}
else if (!strcmp(s, "colours")) {
if (ISOS == 0) {
eprintf( "colours with no previous correct isos parameter\n");
......@@ -450,6 +536,9 @@ int loadConfigFile(const char * f)
char file[256];
sprintf (file, "%s%s", PATH, s);
fixFile(file);
if (atoms) {
cleanAtoms(&numAtoms, TIMESTEPS, &atoms);
}
int e;
e=readAtomsXYZ(file, &numAtoms, &timesteps, &atoms);
if (e<0)
......@@ -461,6 +550,9 @@ int loadConfigFile(const char * f)
r=readString(F, s);
if (r!=0)
return -14;
if (atoms) {
cleanAtoms(&numAtoms, TIMESTEPS, &atoms);
}
int timesteps=TIMESTEPS;
char file[256];
sprintf(file, "%s%s", PATH, s);
......@@ -497,6 +589,9 @@ int loadConfigFile(const char * f)
int e;
int timesteps;
//rgh fixme, we know only one
if (atoms) {
cleanAtoms(&numAtoms, timesteps, &atoms);
}
e = readAtomsJson (file, &numAtoms, &timesteps, &atoms, abc, &clonedAtoms);
if (e<0)
return e-300;
......@@ -515,9 +610,11 @@ int loadConfigFile(const char * f)
int timesteps;
//rgh fixme, we know only one
e = readAtomsAnalyticsJson(file, &numAtoms, &timesteps, &atoms, abc, &clonedAtoms);
if (e<0)
return e - 400;
if (e<0) {
//cleanup
return e - 400;
}
if (has_abc)
numClonedAtoms = clonedAtoms[0].size() / 4;
else
......@@ -711,6 +808,11 @@ int loadConfigFile(const char * f)
r=fscanf (F, "%f %f", &nearclip, &farclip);
if (r<2)
eprintf ("Error reading clippingplanes values");
}
else if (!strcmp(s, "cutplanes")) {
r = fscanf(F, "%f %f", &nearcut, &farcut);
if (r<2)
eprintf("Error reading clippingplanes values");
}else if (!strcmp (s, "bondscolour")) {
r=fscanf (F, "%f %f %f", bondscolours, bondscolours+1, bondscolours+2);
if (r<3)
......@@ -753,6 +855,8 @@ int loadConfigFile(const char * f)
menubutton = Record;
else if (!strcmp(s, "Infobox"))
menubutton = Infobox;
else if (!strcmp(s, "CuttingPlane"))
menubutton = CuttingPlane;
else if (!strcmp (s, "Nothing"))
menubutton = Nothing;
else eprintf ("Unknown menubutton parameter %s\n", s);
......@@ -792,6 +896,13 @@ int loadConfigFile(const char * f)
if (r<3) {
eprintf ("Error reading server paramters");
}
} else if (!strcmp (s, "chainfile")) {
r=readString(F, s);
if (r!=0)
return -21;
r=readChains (s);
if (r!=0)
return -21;
} else {
eprintf( "Unrecognized parameter %s\n", s);
for (int i=0;i<strlen(s);i++)
......
......@@ -26,6 +26,7 @@ extern char * SCREENSHOT;
extern int ISOS;
extern float **isocolours; // [ISOS][4];
extern const char **plyfiles;
extern const char *** fullplyfiles; //explicit plyfiles for all timesteps
extern float **translations;
extern float userpos[3];
extern float scaling;
......@@ -68,6 +69,7 @@ extern bool gazenavigation;
extern int transparencyquality;
extern float nearclip, farclip;
extern float nearcut, farcut;
extern float animationspeed; //how fast to change to next timestep
extern float movementspeed; //how fast to move the user
......@@ -85,7 +87,7 @@ int loadConfigFile(const char * f);
//for multiuser
extern int secret;
extern char * server;
extern const char * server;
extern int port;
extern bool resetTimestepOnReload;
......@@ -101,6 +103,7 @@ struct information {
typedef enum {
Record,
Infobox,
CuttingPlane,
Nothing
} menubutton_t;
......
......@@ -21,6 +21,9 @@ bool has_abc = false;
int* numAtoms; //[timesteps]
float **atoms; //[timesteps][numAtoms[i]*4] //xyzu, u=atom number
int *atomAffiliations;
int numChains;
float *chainColours; //[numChains+1][4];
bool fixedAtoms;
float cubetrans[3];
......
......@@ -22,6 +22,9 @@ extern bool has_abc;
extern int* numAtoms; //[timesteps]
extern float **atoms; //[timesteps][numAtoms[i]*4] //xyzu, u=atom number
extern int *atomAffiliations;
extern int numChains;
extern float *chainColours; //[numChains+1][4]; 0=default bond colour
extern bool fixedAtoms; //all timesteps use the atoms for timestep 0. Used for excitons etc.
extern float cubetrans[3];
......
......@@ -50,14 +50,19 @@ const char * const IsoShaders [] = {"Iso Renderer",
"void main()\n"
"{\n"
"lowp vec3 nn=normalize(vnormal);"
"lowp float a=max(0.0, dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
"lowp float b=max(0.0, dot(nn, vec3(0,0,1)));\n"
//two faced normal
"lowp float a=abs (dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
"lowp float b=abs (dot(nn, vec3(0,0,1)));\n"
"highp vec4 res=vcolor;\n"
" outputColor = vec4 ((res.rgb) * (0.2 + 0.2*a + 0.3*b), vcolor.a);\n"
"}\n"
,
//tess
nullptr
//tess eval
nullptr,
//geometry
nullptr,
//tcs
nullptr,
};
const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
......@@ -100,13 +105,19 @@ const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
"if ((pos.z/pos.w+1.0)/2.0 <= mytex.r+0.00001 ) discard;\n"
"lowp vec3 nn=normalize(n);"
"lowp float a=max(0.0, dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
"lowp float b=max(0.0, dot(nn, vec3(0,0,1)));\n"
"lowp float a=abs(dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
"lowp float b=abs(dot(nn, vec3(0,0,1)));\n"
"highp vec4 res=color;\n"
" outputColor = vec4 ((res.rgb) * (0.2 + 0.2*a + 0.3*b), color.a);\n"
"}\n",
nullptr
//tess eval
nullptr,
//geometry
nullptr,
//tcs
nullptr,
};
const char *const IsoBlendShaders [] = {"Iso Transparent Blend",
......@@ -137,5 +148,10 @@ const char *const IsoBlendShaders [] = {"Iso Transparent Blend",
"{\n"
" outputColor = texture( diffuse, v2TexCoord);\n"
"}\n",
nullptr
//tess eval
nullptr,
//geometry
nullptr,
//tcs
nullptr,
};
......@@ -65,7 +65,7 @@ bool AddModelToScene( const float *mat/*[16]*/, std::vector<float> &vertdata,
#else
std::vector<GLuint> & vertindices,
#endif
const char * model, bool water, bool colours, int set)
const char * model, bool useisotrans, bool colours, int set)
{
CurrentVertex=-1;
......@@ -142,8 +142,13 @@ bool AddModelToScene( const float *mat/*[16]*/, std::vector<float> &vertdata,
for (int j = 0; j < 4; j++)
vertdata.push_back(isocolours[set][j]);
} else {
for (int j = 0; j < 4; j++)
for (int j = 0; j < 3; j++)
vertdata.push_back(CubeVertices[i * numComponents + 6 + j]);
if (useisotrans)
vertdata.push_back(isocolours[set][3]);
else
vertdata.push_back(CubeVertices[i * numComponents + 6 + 3]); //trans
}
}
delete[] CubeVertices;
......@@ -268,7 +273,7 @@ GLenum PrepareISOTransShader (GLuint *p, GLint *mat, GLuint *b) {
*mat=glGetUniformLocation(*p, "matrix");
if( *mat == -1 )
{
eprintf( "Unable to find matrix uniform in ISO shader\n" );
eprintf( "Unable to find matrix uniform in ISO shader (%s)\n", IsoTransparentShaders[SHADERNAME]);
}
*b=CompileGLShader(
......