NOMAD Cardboard changes:

-Support Alcatel Flash Plus 2 with Android 6.0 (from Berlin FHI)
-Allow android api level 23
-Add icon
-Add file picker on init
-Display transparent isos using additive blending
-Make shaders gles 3.0 compatible
-Update to latest NOMAD VR Lib
parent 14a108c1
......@@ -8,7 +8,7 @@ model {
defaultConfig.with {
applicationId = "com.google.vr.ndk.samples.treasurehunt"
minSdkVersion.apiLevel = 19
targetSdkVersion.apiLevel = 24
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
......
......@@ -27,6 +27,7 @@
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="NOMADgvrT"
android:theme="@style/VrActivityTheme">
<activity
......
......@@ -79,23 +79,63 @@ public static void verifyStoragePermissions(Activity activity) {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, android.content.Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==123 && resultCode==RESULT_OK) {
String s=data.getDataString();
android.util.Log.d("NOMADgvrT","OnActivityResult, s="+s);
String uriString="";
if (s.startsWith("file://")) {
uriString=s.substring(7);
} else if (s.startsWith("content://com.asus.filemanager.OpenFileProvider/file")) {
uriString=s.substring(52);
} else {
uriString=s;
}
android.util.Log.d("NOMADgvrT","OnActivityResult, uri="+uriString);
nativeSetConfigFile(uriString, android.os.Environment.getExternalStorageDirectory().getPath() + "/");
nativeLoadConfigFile(nativeTreasureHuntRenderer);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
verifyStoragePermissions(this);
//http://stackoverflow.com/questions/36557879/how-to-use-native-android-file-open-dialog
/////////
//setContentView(R.layout.activity_main);
///////////
String externalsd=android.os.Environment.getExternalStorageDirectory().getPath() + "/";
//intents
android.content.Intent intent = getIntent();
String s=intent.getDataString();
String uriString=externalsd+"material.ncfg";
if (s==null)
android.util.Log.d("NOMADgvrT","String intent is null");
if (s==null) {
android.util.Log.d("NOMADgvrT","String intent is null");
android.content.Intent intentSent = new android.content.Intent()
.setType("*/*")
.setAction(android.content.Intent.ACTION_GET_CONTENT);
startActivityForResult(android.content.Intent.createChooser(intentSent, "Select NOMAD VR config file (.ncfg)"), 123);
s=intentSent.getDataString();
}
else
android.util.Log.d("NOMADgvrT","String intent is <"+ s+">");
android.util.Log.d("NOMADgvrT","String intent finally is <"+s+">");
if (s!=null) {
if (s.startsWith("content://")) {
if (s.startsWith("content://")) {//this only works with ncfg with no associated data
android.util.Log.d("NOMADgvrT","String intent is <"+s+">");
try {
java.io.InputStream input = getContentResolver().openInputStream(intent.getData());
byte[] buffer = new byte[8 * 1024];
......@@ -289,4 +329,26 @@ public static void verifyStoragePermissions(Activity activity) {
private native void nativeOnResume(long nativeTreasureHuntRenderer);
private native void nativeSetConfigFile(String s, String e);
private native void nativeLoadConfigFile(long nativeTreasureHuntRenderer);
public void DisplayMessage (final String s)
{
//http://stackoverflow.com/questions/3875184/cant-create-handler-inside-thread-that-has-not-called-looper-prepare
//rgh: this hangs, need to investigate
new Thread()
{
public void run()
{
MainActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
android.widget.Toast toast = android.widget.Toast.makeText(MainActivity.this.getApplicationContext(), s,
android.widget.Toast.LENGTH_LONG);
}
});
}
}.start();
}
}
//http://stackoverflow.com/questions/4875114/android-save-image-from-url-onto-sd-card
class NOMAD {
public static boolean i=false;
public static void Init ()
//we are going to block anyway until we have the datasets
{
if (android.os.Build.VERSION.SDK_INT > 9) {
android.os.StrictMode.ThreadPolicy policy = new android.os.StrictMode.ThreadPolicy.Builder().permitAll().build();
android.os.StrictMode.setThreadPolicy(policy);
}
i=true;
}
public static void GetUrl (String url, String path)
{
if (!i)
Init();
android.util.Log.d("NOMAD", "Java NOMAD.GetUrlThread(\""+url+"\",\""+path+"\") called");
try {
java.net.URL u = new java.net.URL(url);
java.net.HttpURLConnection urlConnection = (java.net.HttpURLConnection) u.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
java.io.File file = new java.io.File(path);
java.io.FileOutputStream fileOutput = new java.io.FileOutputStream(file);
int status = urlConnection.getResponseCode();
if (status != java.net.HttpURLConnection.HTTP_OK) {
return; //http error or redirect, we probably want to exit here as NOMAD encyclopedia should not do that
}
java.io.InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 )
{
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
}
fileOutput.close();
} //try
catch (Exception e) {
e.printStackTrace();
}
} //GetUrl
} //class NOMAD
......@@ -23,10 +23,16 @@
#include "vr/gvr/capi/include/gvr_audio.h"
#include "NOMADVRLib/atoms.hpp" //for TMPDIR
#include "treasure_hunt_jni.h"
#define JNI_METHOD(return_type, method_name) \
JNIEXPORT return_type JNICALL \
Java_com_google_vr_ndk_samples_treasurehunt_MainActivity_##method_name
//http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls
JavaVM* javaVM = nullptr;
jobject jo;
namespace {
inline jlong jptr(TreasureHuntRenderer *native_treasure_hunt) {
......@@ -38,6 +44,28 @@ inline TreasureHuntRenderer *native(jlong ptr) {
}
} // anonymous namespace
//http://stackoverflow.com/questions/28622036/android-ndk-calling-java-functions-from-c
/*void GetUrl (const char *url, const char *path)
{
jstring jurl = genv->NewStringUTF(url);
jstring jpath = genv->NewStringUTF(path);
jclass jc = genv->FindClass("NOMAD");
jmethodID mid = genv->GetStaticMethodID(jc, "GetUrl", "(Ljava/lang/String;Ljava/lang/String;)V");
genv->CallStaticVoidMethod(jc, mid, jurl, jpath);
}*/
void DisplayMessage (const char *s)
{
JNIEnv *env;
javaVM->AttachCurrentThread(&env, nullptr);
jstring js = env->NewStringUTF(s);
jclass cls = env->GetObjectClass(jo);
jmethodID mid = env->GetMethodID(cls, "DisplayMessage", "(Ljava/lang/String;)V");
env->CallVoidMethod(jo, mid, js);
}
extern "C" {
JNI_METHOD(jlong, nativeCreateRenderer)
......@@ -82,11 +110,20 @@ JNI_METHOD(void, nativeOnResume)
native(native_treasure_hunt)->OnResume();
}
//https://library.vuforia.com/articles/Solution/How-To-Communicate-Between-Java-and-C-using-the-JNI
JNI_METHOD(void, nativeSetConfigFile)
(JNIEnv *env, jobject obj, jstring s, jstring e) {
env->GetJavaVM(&javaVM);
jo=env->NewGlobalRef(obj);
configPath = env->GetStringUTFChars(s , NULL ) ;
TMPDIR=env->GetStringUTFChars(e , NULL ) ;
}
JNI_METHOD(void, nativeLoadConfigFile)
(JNIEnv *env, jobject obj, jlong native_treasure_hunt) {
native(native_treasure_hunt)->loadConfigFile();
}
} // extern "C"
//void GetUrl (const char *url, const char *path);
void DisplayMessage (const char *s);
......@@ -16,6 +16,7 @@
#include <unistd.h>
#include "treasure_hunt_renderer.h" // NOLINT
#include "treasure_hunt_jni.h"
#include <android/log.h>
#include <assert.h>
......@@ -33,7 +34,7 @@
#include "NOMADVRLib/polyhedron.h"
#include "NOMADVRLib/IsosurfacesGL.h"
#define LOG_TAG "TreasureHuntCPP"
#define LOG_TAG "NOMADgvrT"
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
......@@ -59,6 +60,8 @@ void eprintf( const char *fmt, ... )
if (*fmt=='\0')
LOGD("Empty format");
LOGD("<%s>", buffer);
//rgh: does not work yet
//DisplayMessage(buffer);
}
......@@ -305,13 +308,8 @@ static float VectorInnerProduct(const std::array<float, 4>& vect1,
}
} // anonymous namespace
TreasureHuntRenderer::TreasureHuntRenderer(
gvr_context* gvr_context, std::unique_ptr<gvr::AudioApi> gvr_audio_api)
: gvr_api_(gvr::GvrApi::WrapNonOwned(gvr_context)),
scratch_viewport_(gvr_api_->CreateBufferViewport()),
gvr_controller_api_(nullptr),
gvr_viewer_type_(gvr_api_->GetViewerType()) {
void TreasureHuntRenderer::loadConfigFile(void)
{
if (configPath!=nullptr)
eprintf ("configPath=<%s>", configPath);
else
......@@ -326,7 +324,7 @@ TreasureHuntRenderer::TreasureHuntRenderer(
chdir(s.substr(0, s.find_last_of("\\/")).c_str());
if ((error=loadConfigFile(configPath))<0) {
if ((error=::loadConfigFile(configPath))<0) {
if (-100<error) {
eprintf(loadConfigFileErrors[-error]);
eprintf("Config file reading error");
......@@ -345,7 +343,17 @@ TreasureHuntRenderer::TreasureHuntRenderer(
LOGD("No atom glyph specified, using Icosahedron");
solid=new Solid(Solid::Type::Icosahedron);
}
eprintf("after config load, timesteps=%d", TIMESTEPS);
}
TreasureHuntRenderer::TreasureHuntRenderer(
gvr_context* gvr_context, std::unique_ptr<gvr::AudioApi> gvr_audio_api)
: gvr_api_(gvr::GvrApi::WrapNonOwned(gvr_context)),
scratch_viewport_(gvr_api_->CreateBufferViewport()),
gvr_controller_api_(nullptr),
gvr_viewer_type_(gvr_api_->GetViewerType()) {
loadConfigFile();
//eprintf("after config load, timesteps=%d", TIMESTEPS);
ResumeControllerApiAsNeeded();
if (gvr_viewer_type_ == GVR_VIEWER_TYPE_CARDBOARD) {
......@@ -374,6 +382,7 @@ void TreasureHuntRenderer::InitializeGl() {
gvr_api_->InitializeGl();
glGenTextures(2, textures);
glGenTextures(2+ZLAYERS, textDepthPeeling);
//white
unsigned char data2[4]={255,255,255,255}; //white texture for non-textured meshes
glBindTexture(GL_TEXTURE_2D, textures[0]);
......@@ -409,7 +418,7 @@ glGenTextures(2, textures);
error=-403;
}
e=SetupAtoms(&AtomTVAO, &AtomTBuffer);
e=SetupAtoms(&AtomTVAO, &AtomTBuffer, &BondIndices);
if (e!=GL_NO_ERROR) {
eprintf ("SetupAtoms error %d", e);
error=-404;
......@@ -428,8 +437,50 @@ glGenTextures(2, textures);
error=-406;
}
// Because we are using 2X MSAA, we can render to half as many pixels and
// achieve similar quality.
render_size_ =
HalfPixelCount(gvr_api_->GetMaximumEffectiveRenderTargetSize());
std::vector<gvr::BufferSpec> specs;
specs.push_back(gvr_api_->CreateBufferSpec());
specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888);
specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
specs[0].SetSize(render_size_);
specs[0].SetSamples(2);
swapchain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs)));
viewport_list_.reset(
new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
//isosurfaces
if (ISOS) {
//rgh: FIXME Additive blending for android; do not need most of these textures
//additive blending means white background makes everything white
float m=BACKGROUND[0];
m=std::max(m, BACKGROUND[1]);
m=std::max(m, BACKGROUND[2]);
if (m>0.2f) { //make background darker, preserving colour, so additive blending works
for (int i=0;i<3;i++)
BACKGROUND[i]*=0.2f / m;
}
e=SetupDepthPeeling(render_size_.width, render_size_.height, ZLAYERS,
textDepthPeeling, &peelingFramebuffer);
if (!e) {
eprintf("Error setting up DepthPeeling\n");
error=-407;
}
if (GL_NO_ERROR!=(e=PrepareISOTransShader (&TransP,
&TransMatrixLoc, &BlendP)))
{
eprintf( "Error Preparing Transparency shader, %d\n", e );
error=-408;
}
SetupBlending(&BlendVAO, &BlendBuffer, &BlendIndices);
PrepareISOShader(&ISOP, &ISOMatrixLoc);
std::vector<float> vertices;
......@@ -501,28 +552,13 @@ glGenTextures(2, textures);
indices.clear();
if (p % ISOS == ISOS - 1) {
eprintf ("timestep %d", timestep);
//eprintf ("timestep %d", timestep);
timestep++;
}
}
}
// Because we are using 2X MSAA, we can render to half as many pixels and
// achieve similar quality.
render_size_ =
HalfPixelCount(gvr_api_->GetMaximumEffectiveRenderTargetSize());
std::vector<gvr::BufferSpec> specs;
specs.push_back(gvr_api_->CreateBufferSpec());
specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888);
specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
specs[0].SetSize(render_size_);
specs[0].SetSamples(2);
swapchain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs)));
viewport_list_.reset(
new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
}
......@@ -621,6 +657,7 @@ if (animateTimesteps) {
// Draw the world.
frame.BindBuffer(0);
if (error<0) {
//rgh: FIXME, add textures with messages here
if (-100<error) {
glClearColor(1.f, 0.f, 0.f, 1.f);
} else if (-200<error){
......@@ -633,7 +670,7 @@ if (animateTimesteps) {
glClearColor(1.f, 0.f, 1.f, 1.f);
}
} else {
glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 0.5f);
glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 1.f);
}
// Dark background so text shows up.
......@@ -764,10 +801,10 @@ for (int i=0;i<4;i++)
t[j*4+i]=transform.m[i][j];
glUseProgram(ISOP);
if ((e = glGetError()) != GL_NO_ERROR)
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("1 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
if ((e = glGetError()) != GL_NO_ERROR)
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("2 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
if (curDataPos!=ISOS) {
......@@ -779,31 +816,58 @@ if (curDataPos!=ISOS) {
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("4 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
} else {
//transparency; FIXME disabled as I get 1fps, with screen in 4 columns and z-check is incorrect
/*
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
//do depth peeling
CleanDepthTexture(textDepthPeeling[0], render_size_.width, render_size_.height);
GLint dfb;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfb);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, before zl loop: %d\n", e);
for (int zl = 0; zl < ZLAYERS; zl++) {
EnableDepthFB(zl, TransP,
peelingFramebuffer, textDepthPeeling);
glUniformMatrix4fv(TransMatrixLoc, 1, GL_FALSE, t);
for (int i=0;i<ISOS;i++) {
glBindVertexArray(ISOVAO[currentSet*ISOS+i]);
glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0);
}
}
glUseProgram(BlendP);
glBindFramebuffer(GL_FRAMEBUFFER, dfb);
glBindVertexArray(BlendVAO);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, after glBindVertexArray: %d\n", e);
BlendTextures(textDepthPeeling, ZLAYERS);
glBindVertexArray(0);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, after BlendTextures: %d\n", e);*/
/* no transparency*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
for (int i=0;i<ISOS;i++) {
glBindVertexArray(ISOVAO[currentSet*ISOS+i]);
glBindBuffer(GL_ARRAY_BUFFER, ISOBuffer[currentSet*ISOS+i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ISOIndices[currentSet*ISOS+i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(0*sizeof(float)));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(3*sizeof(float)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(6*sizeof(float)));
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("5 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
eprintf ("Drawing %d vertices, isos", numISOIndices[currentSet*ISOS+i]);
glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("6 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
}
}
glDisable(GL_BLEND);
} //if (curDataPos!=ISOS)
//eprintf ("end of RenderIsos");
glBindVertexArray(0);
}
void TreasureHuntRenderer::RenderAtoms(const float *m) //m[16]
{
//return;
eprintf ("RenderAtoms start numatoms %d, timestep %d", numAtoms[currentSet], currentSet);
eprintf ("solid nfaces %d", solid->nFaces);
//eprintf ("RenderAtoms start numatoms %d, timestep %d", numAtoms[currentSet], currentSet);
//eprintf ("solid nfaces %d", solid->nFaces);
int e;
if (numAtoms==0)
return;
......@@ -977,7 +1041,7 @@ void TreasureHuntRenderer::RenderUnitCell(const gvr::Mat4f eyeViewProjection)
//for (int i=0;i<4;i++)
// for (int j=0;j<4;j++)
// eprintf ("%d %d = %f", i, j, eyeViewProjection.m[i][j]);
eprintf ("RenderUnitCell, has_abc=%d", has_abc);
//eprintf ("RenderUnitCell, has_abc=%d", has_abc);
if (!has_abc)
return;
if (UnitCellVAO==0)
......
......@@ -30,6 +30,8 @@
#include "vr/gvr/capi/include/gvr_controller.h"
#include "vr/gvr/capi/include/gvr_types.h"
#define ZLAYERS 2
extern const char * configPath;
class TreasureHuntRenderer {
......@@ -69,6 +71,7 @@ class TreasureHuntRenderer {
*/
void OnResume();
void OnTriggerEvent();
void loadConfigFile(void);
private:
int CreateTexture(int width, int height, int textureFormat, int textureType);
......@@ -150,17 +153,23 @@ int currentset;
gvr::ViewerType gvr_viewer_type_;
GLuint textures[2]; // white, atoms
GLuint textDepthPeeling[ZLAYERS+2];
GLuint peelingFramebuffer;
//if no tesselation is available, we still need the tess atoms for the trajectories!
GLuint *AtomTVAO=nullptr, *AtomTBuffer=nullptr, *AtomVAO=nullptr, *AtomBuffer=nullptr, *AtomIndices=nullptr,//[2], atoms, extraatoms
BondIndices,
UnitCellVAO, UnitCellBuffer, UnitCellIndexBuffer;
GLuint AtomsP, UnitCellP; // framework does not provide support for tesselation and provides many things we don't need.
GLint AtomMatrixLoc, UnitCellMatrixLoc, UnitCellColourLoc;
GLuint TransP=0, BlendP=0;
GLint TransMatrixLoc=-1;
bool hasTess=true;
GLuint *ISOVAO=nullptr/*[ISOS*TIMESTEPS]*/, *ISOBuffer=nullptr/*[ISOS*TIMESTEPS]*/,
*ISOIndices=nullptr/*[ISOS*TIMESTEPS]*/;
GLuint ISOP;
GLint ISOMatrixLoc;
GLuint BlendVAO=0, BlendBuffer=0, BlendIndices=0;
int *numISOIndices=nullptr/*[ISOS*TIMESTEPS]*/;
int currentSet=0;
......
......@@ -65,9 +65,9 @@ const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
" color = vec4(colorIn.rgba);\n"
" n=normalize(normalsIn);\n"
// " uv=uvIn;\n"
"int i=gl_InstanceID / " GRIDSTR ";\n"
"int j=gl_InstanceID % " GRIDSTR ";\n"
" pos = matrix * (position + vec4 (float(i)*0.15*101.0, 0, float(j)*0.15*101.0, 0));\n"
// "int i=gl_InstanceID / " GRIDSTR ";\n"
// "int j=gl_InstanceID % " GRIDSTR ";\n"
" pos = matrix * (position /*+ vec4 (float(i)*0.15*101.0, 0, float(j)*0.15*101.0, 0)*/);\n"
" gl_Position = pos;\n"
//" gl_Position = matrix * position;\n"
"}\n",
......@@ -79,17 +79,17 @@ const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
"#version 300 es\n"
#endif
"uniform sampler2D diffuse;\n" //now extra depth texture for peeling
"in vec4 color;\n"
"in vec3 n;\n"
"in lowp vec4 color;\n"
"in lowp vec3 n;\n"
"in highp vec4 pos;\n"
"out vec4 outputColor;\n"
"out lowp vec4 outputColor;\n"
"void main()\n"
"{\n"
"vec4 mytex=texture(diffuse, vec2(pos.x/pos.w*0.5+0.5, pos.y/pos.w*0.5+0.5));\n"
"highp vec4 mytex=texture(diffuse, vec2(pos.x/pos.w*0.5+0.5, pos.y/pos.w*0.5+0.5));\n"
//http://www.gamedev.net/topic/556521-glsl-manual-shadow-map-biasscale/
//"vec2 d=vec2(dFdx(pos.z), dFdy(pos.z));\n"
//"highp float m=sqrt(d.x*d.x + d.y*d.y);\n"
"if ((pos.z/pos.w+1)/2 <= mytex.r+0.0001 ) discard;\n"
"if ((pos.z/pos.w+1.0)/2.0 <= mytex.r+0.0001 ) 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"
......@@ -118,10 +118,14 @@ const char *const IsoBlendShaders [] = {"Iso Transparent Blend",
" gl_Position = vec4(position, 1);\n"
"}\n",
//fragment shader
#if defined(WIN32) || defined(CAVE)
"#version 410 core\n"
#else
"#version 300 es\n"
#endif
"uniform sampler2D diffuse;\n"
"in vec2 v2TexCoord;\n"
"out vec4 outputColor;\n"
"in highp vec2 v2TexCoord;\n"
"out lowp vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = texture( diffuse, v2TexCoord);\n"
......
......@@ -131,7 +131,7 @@ const char * const AtomShadersNoTess [] = {
"lowp float a=abs(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"
"highp vec4 res=color;\n"
" outputColor = vec4 ((res.rgb) * (0.1 + 0.2*a), color.a);\n"
" outputColor = vec4 ((res.rgb) * (0.4 + 0.3*a + 0.3*b), color.a);\n"
"}\n",
//tess eval
nullptr
......
......@@ -393,6 +393,7 @@ if (r<2) {
//possibly https or other unsupported protocol, fall back to wget
return readAtomsJsonURLwget (f, numatoms, timesteps, pos, abc, clonedAtoms, token);
#else
//GetUrl("https://www.google.de/", "google_index.html"); //rgh test
return -3;
#endif
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment